void CmdVariable::PrintVariable(DebuggerClient &client, const String& varName) { CmdVariable cmd(client.isStackTraceAsync() ? KindOfVariableAsync : KindOfVariable); auto charCount = client.getDebuggerClientShortPrintCharCount(); cmd.m_frame = client.getFrame(); auto rcmd = client.xend<CmdVariable>(&cmd); always_assert(rcmd->m_version == 2); // Using the new protocol. rcmd contains a list of variables only. Fetch // value of varName only, so that we can recover nicely when its value is too // large to serialize. cmd.m_varName = varName; cmd.m_variables.reset(); cmd.m_formatMaxLen = charCount; cmd.m_version = 2; rcmd = client.xend<CmdVariable>(&cmd); if (rcmd->m_variables.empty()) { // Perhaps the value is too large? See recvImpl. Retry the command with // version 1, in which case values are omitted. cmd.m_version = 1; rcmd = client.xend<CmdVariable>(&cmd); if (!rcmd->m_variables.empty()) { // It's there without values, and gone with values, so it is too large. client.output(s_omitted); } return; } auto const get_var = [varName] (const CmdVariable& cmd) { assert(cmd.m_variables.size() == 1); assert(cmd.m_variables.exists(varName, true /* isKey */)); assert(cmd.m_variables[varName].isString()); return cmd.m_variables[varName].toString(); }; auto const value = get_var(*rcmd); if (charCount <= 0 || value.size() <= charCount) { client.output(value); return; } // Don't show the "omitted" suffix. client.output(StringSlice(value.data(), charCount)); if (client.ask("There are more characters. Continue? [y/N]") == 'y') { // Now we get the full value, and show the rest. cmd.m_variables.reset(); cmd.m_formatMaxLen = -1; rcmd = client.xend<CmdVariable>(&cmd); auto value = get_var(*rcmd); auto rest = StringSlice(value.data() + charCount, value.size() - charCount); client.output(rest); client.tutorial("You can use 'set cc n' to increase the character" " limit. 'set cc -1' will remove the limit."); } }
StringData* StringData::Make(const char* data, size_t len, CopyStringMode) { if (UNLIKELY(len > StringData::MaxSize)) { throw_string_too_large(len); } return Make(StringSlice(data, len), CopyString); }
StringData* StringData::Make(char* data, size_t len, AttachStringMode) { if (UNLIKELY(len > StringData::MaxSize)) { throw_string_too_large(len); } auto const sd = Make(StringSlice(data, len), CopyString); free(data); assert(sd->checkSane()); return sd; }
String &String::operator+=(litstr s) { if (s && *s) { if (empty()) { m_px = StringData::Make(s, CopyString); m_px->setRefCount(1); } else if (m_px->getCount() == 1) { auto const tmp = m_px->append(StringSlice(s, strlen(s))); if (UNLIKELY(tmp != m_px)) StringBase::operator=(tmp); } else { StringData* px = StringData::Make(m_px, s); px->setRefCount(1); decRefStr(m_px); m_px = px; } } return *this; }
void ExtractDataMain(int argc, char* const* argv) { args::Parser parser(argv[0], "Extracts game data from zip archives into a directory"); String source; String dest; Optional<String> plugin; parser.add_argument("source", store(source)) .help("directory in which to store or expect zip files") .required(); parser.add_argument("dest", store(dest)) .help("place output in this directory") .required(); parser.add_argument("plugin", store(plugin)) .help("a plugin to install (default: install factory scenario)"); parser.add_argument("-h", "--help", help(parser, 0)) .help("display this help screen"); try { String error; if (!parser.parse_args(argc - 1, argv + 1, error)) { print(io::err, format("{0}: {1}\n", parser.name(), error)); exit(1); } DataExtractor extractor(source, dest); if (plugin.has()) { extractor.set_plugin_file(*plugin); } if (extractor.current()) { print(io::err, format("{0} is up-to-date!\n", dest)); } else { print(io::err, format("Extracting to {0}...\n", dest)); PrintStatusObserver observer; extractor.extract(&observer); print(io::err, StringSlice("done.\n")); } } catch (Exception& e) { print(io::err, format("{0}: {1}\n", utf8::decode(argv[0]), e.message())); exit(1); } }
StringData* StringData::Make(StringSlice s1, const char* lit2) { return Make(s1, StringSlice(lit2, strlen(lit2))); }
String& String::operator+=(const MutableSlice& slice) { return (*this += StringSlice(slice.begin(), slice.size())); }
String wrap(const char* value) { return wrap(StringSlice(value)); }