lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options) : ReadBufferAndDumpToStreamOptions() { SetStream(options.GetStream()); SetPrefixToken(options.GetPrefixToken()); SetSuffixToken(options.GetSuffixToken()); SetQuote(options.GetQuote()); SetEscapeNonPrintables(options.GetEscapeNonPrintables()); SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); SetLanguage(options.GetLanguage()); }
bool StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (const ReadStringAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); Error my_error; ProcessSP process_sp(options.GetProcessSP()); if (process_sp.get() == nullptr || options.GetLocation() == 0) return false; size_t size; const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); bool is_truncated = false; if (options.GetSourceSize() == 0) size = max_size; else if (!options.GetIgnoreMaxLength()) { size = options.GetSourceSize(); if (size > max_size) { size = max_size; is_truncated = true; } } else size = options.GetSourceSize(); lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error); if (my_error.Fail()) return false; const char* prefix_token = options.GetPrefixToken(); char quote = options.GetQuote(); if (prefix_token != 0) options.GetStream()->Printf("%s%c",prefix_token,quote); else if (quote != 0) options.GetStream()->Printf("%c",quote); uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); const bool escape_non_printables = options.GetEscapeNonPrintables(); lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; if (escape_non_printables) { if (Language *language = Language::FindPlugin(options.GetLanguage())) escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); else escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); } // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) { if (escape_non_printables) { uint8_t* next_data = nullptr; auto printable = escaping_callback(data, data_end, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) { // GetPrintable() failed on us - print one byte in a desperate resync attempt printable_bytes = data; printable_size = 1; next_data = data+1; } for (unsigned c = 0; c < printable_size; c++) options.GetStream()->Printf("%c", *(printable_bytes+c)); data = (uint8_t*)next_data; } else { options.GetStream()->Printf("%c",*data); data++; } } const char* suffix_token = options.GetSuffixToken(); if (suffix_token != 0) options.GetStream()->Printf("%c%s",quote, suffix_token); else if (quote != 0) options.GetStream()->Printf("%c",quote); if (is_truncated) options.GetStream()->Printf("..."); return true; }