blob: a5ed7e45cdfde7ecea8f0ea9059870d4dfc32e4c [file] [log] [blame]
Enrico Granataca6c8ee2014-10-30 01:45:39 +00001//===-- StringPrinter.cpp ----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/DataFormatters/StringPrinter.h"
11
12#include "lldb/Core/DataExtractor.h"
Enrico Granataebdc1ac2014-11-05 21:20:48 +000013#include "lldb/Core/Debugger.h"
Enrico Granataca6c8ee2014-10-30 01:45:39 +000014#include "lldb/Core/Error.h"
Enrico Granataebdc1ac2014-11-05 21:20:48 +000015#include "lldb/Core/ValueObject.h"
Enrico Granataca6c8ee2014-10-30 01:45:39 +000016#include "lldb/Target/Process.h"
17#include "lldb/Target/Target.h"
18
19#include "llvm/Support/ConvertUTF.h"
20
Enrico Granataca6c8ee2014-10-30 01:45:39 +000021#include <ctype.h>
Enrico Granataca6c8ee2014-10-30 01:45:39 +000022#include <locale>
23
24using namespace lldb;
25using namespace lldb_private;
26using namespace lldb_private::formatters;
27
Enrico Granataca6c8ee2014-10-30 01:45:39 +000028// we define this for all values of type but only implement it for those we care about
29// that's good because we get linker errors for any unsupported type
30template <StringElementType type>
Enrico Granataad650a12015-09-09 20:59:49 +000031static StringPrinter::StringPrinterBufferPointer<>
Enrico Granataca6c8ee2014-10-30 01:45:39 +000032GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next);
33
34// mimic isprint() for Unicode codepoints
35static bool
36isprint(char32_t codepoint)
37{
38 if (codepoint <= 0x1F || codepoint == 0x7F) // C0
39 {
40 return false;
41 }
42 if (codepoint >= 0x80 && codepoint <= 0x9F) // C1
43 {
44 return false;
45 }
46 if (codepoint == 0x2028 || codepoint == 0x2029) // line/paragraph separators
47 {
48 return false;
49 }
50 if (codepoint == 0x200E || codepoint == 0x200F || (codepoint >= 0x202A && codepoint <= 0x202E)) // bidirectional text control
51 {
52 return false;
53 }
54 if (codepoint >= 0xFFF9 && codepoint <= 0xFFFF) // interlinears and generally specials
55 {
56 return false;
57 }
58 return true;
59}
60
61template <>
Enrico Granataad650a12015-09-09 20:59:49 +000062StringPrinter::StringPrinterBufferPointer<>
Enrico Granataca6c8ee2014-10-30 01:45:39 +000063GetPrintableImpl<StringElementType::ASCII> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
64{
Enrico Granataad650a12015-09-09 20:59:49 +000065 StringPrinter::StringPrinterBufferPointer<> retval = {nullptr};
Enrico Granataca6c8ee2014-10-30 01:45:39 +000066
67 switch (*buffer)
68 {
Enrico Granatada04fbb2014-12-18 19:43:29 +000069 case 0:
70 retval = {"\\0",2};
71 break;
Enrico Granataca6c8ee2014-10-30 01:45:39 +000072 case '\a':
73 retval = {"\\a",2};
74 break;
75 case '\b':
76 retval = {"\\b",2};
77 break;
78 case '\f':
79 retval = {"\\f",2};
80 break;
81 case '\n':
82 retval = {"\\n",2};
83 break;
84 case '\r':
85 retval = {"\\r",2};
86 break;
87 case '\t':
88 retval = {"\\t",2};
89 break;
90 case '\v':
91 retval = {"\\v",2};
92 break;
93 case '\"':
94 retval = {"\\\"",2};
95 break;
96 case '\\':
97 retval = {"\\\\",2};
98 break;
99 default:
100 if (isprint(*buffer))
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000101 retval = {buffer,1};
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000102 else
103 {
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000104 uint8_t* data = new uint8_t[5];
105 sprintf((char*)data,"\\x%02x",*buffer);
106 retval = {data, 4, [] (const uint8_t* c) {delete[] c;} };
107 break;
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000108 }
109 }
110
111 next = buffer + 1;
112 return retval;
113}
114
115static char32_t
116ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1)
117{
118 return (c0-192)*64+(c1-128);
119}
120static char32_t
121ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2)
122{
123 return (c0-224)*4096+(c1-128)*64+(c2-128);
124}
125static char32_t
126ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3)
127{
128 return (c0-240)*262144+(c2-128)*4096+(c2-128)*64+(c3-128);
129}
130
131template <>
Enrico Granataad650a12015-09-09 20:59:49 +0000132StringPrinter::StringPrinterBufferPointer<>
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000133GetPrintableImpl<StringElementType::UTF8> (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
134{
Enrico Granataad650a12015-09-09 20:59:49 +0000135 StringPrinter::StringPrinterBufferPointer<> retval {nullptr};
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000136
137 unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer);
138
139 if (1+buffer_end-buffer < utf8_encoded_len)
140 {
141 // I don't have enough bytes - print whatever I have left
142 retval = {buffer,static_cast<size_t>(1+buffer_end-buffer)};
143 next = buffer_end+1;
144 return retval;
145 }
146
147 char32_t codepoint = 0;
148 switch (utf8_encoded_len)
149 {
150 case 1:
151 // this is just an ASCII byte - ask ASCII
152 return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
153 case 2:
154 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1));
155 break;
156 case 3:
157 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2));
158 break;
159 case 4:
160 codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1), (unsigned char)*(buffer+2), (unsigned char)*(buffer+3));
161 break;
162 default:
163 // this is probably some bogus non-character thing
164 // just print it as-is and hope to sync up again soon
165 retval = {buffer,1};
166 next = buffer+1;
167 return retval;
168 }
169
170 if (codepoint)
171 {
172 switch (codepoint)
173 {
Enrico Granatada04fbb2014-12-18 19:43:29 +0000174 case 0:
175 retval = {"\\0",2};
176 break;
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000177 case '\a':
178 retval = {"\\a",2};
179 break;
180 case '\b':
181 retval = {"\\b",2};
182 break;
183 case '\f':
184 retval = {"\\f",2};
185 break;
186 case '\n':
187 retval = {"\\n",2};
188 break;
189 case '\r':
190 retval = {"\\r",2};
191 break;
192 case '\t':
193 retval = {"\\t",2};
194 break;
195 case '\v':
196 retval = {"\\v",2};
197 break;
198 case '\"':
199 retval = {"\\\"",2};
200 break;
201 case '\\':
202 retval = {"\\\\",2};
203 break;
204 default:
205 if (isprint(codepoint))
206 retval = {buffer,utf8_encoded_len};
207 else
208 {
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000209 uint8_t* data = new uint8_t[11];
210 sprintf((char*)data,"\\U%08x",codepoint);
211 retval = { data,10,[] (const uint8_t* c) {delete[] c;} };
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000212 break;
213 }
214 }
215
216 next = buffer + utf8_encoded_len;
217 return retval;
218 }
219
220 // this should not happen - but just in case.. try to resync at some point
221 retval = {buffer,1};
222 next = buffer+1;
223 return retval;
224}
225
226// Given a sequence of bytes, this function returns:
227// a sequence of bytes to actually print out + a length
228// the following unscanned position of the buffer is in next
Enrico Granataad650a12015-09-09 20:59:49 +0000229static StringPrinter::StringPrinterBufferPointer<>
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000230GetPrintable(StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next)
231{
232 if (!buffer)
233 return {nullptr};
234
235 switch (type)
236 {
237 case StringElementType::ASCII:
238 return GetPrintableImpl<StringElementType::ASCII>(buffer, buffer_end, next);
239 case StringElementType::UTF8:
240 return GetPrintableImpl<StringElementType::UTF8>(buffer, buffer_end, next);
241 default:
242 return {nullptr};
243 }
244}
245
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000246// use this call if you already have an LLDB-side buffer for the data
247template<typename SourceDataType>
248static bool
249DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
250 const SourceDataType*,
251 UTF8**,
252 UTF8*,
253 ConversionFlags),
Enrico Granatad07f7552015-07-17 01:03:59 +0000254 const ReadBufferAndDumpToStreamOptions& dump_options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000255{
Enrico Granatad07f7552015-07-17 01:03:59 +0000256 Stream &stream(*dump_options.GetStream());
257 if (dump_options.GetPrefixToken() != 0)
258 stream.Printf("%c",dump_options.GetPrefixToken());
259 if (dump_options.GetQuote() != 0)
260 stream.Printf("%c",dump_options.GetQuote());
261 auto data(dump_options.GetData());
262 auto source_size(dump_options.GetSourceSize());
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000263 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
264 {
265 const int bufferSPSize = data.GetByteSize();
Enrico Granatad07f7552015-07-17 01:03:59 +0000266 if (dump_options.GetSourceSize() == 0)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000267 {
268 const int origin_encoding = 8*sizeof(SourceDataType);
Enrico Granatad07f7552015-07-17 01:03:59 +0000269 source_size = bufferSPSize/(origin_encoding / 4);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000270 }
271
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000272 const SourceDataType *data_ptr = (const SourceDataType*)data.GetDataStart();
Enrico Granatad07f7552015-07-17 01:03:59 +0000273 const SourceDataType *data_end_ptr = data_ptr + source_size;
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000274
Enrico Granatad07f7552015-07-17 01:03:59 +0000275 const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator();
276
277 if (zero_is_terminator)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000278 {
Enrico Granatad07f7552015-07-17 01:03:59 +0000279 while (data_ptr < data_end_ptr)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000280 {
Enrico Granatad07f7552015-07-17 01:03:59 +0000281 if (!*data_ptr)
282 {
283 data_end_ptr = data_ptr;
284 break;
285 }
286 data_ptr++;
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000287 }
Enrico Granatad07f7552015-07-17 01:03:59 +0000288
289 data_ptr = (const SourceDataType*)data.GetDataStart();
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000290 }
291
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000292 lldb::DataBufferSP utf8_data_buffer_sp;
293 UTF8* utf8_data_ptr = nullptr;
294 UTF8* utf8_data_end_ptr = nullptr;
295
296 if (ConvertFunction)
297 {
298 utf8_data_buffer_sp.reset(new DataBufferHeap(4*bufferSPSize,0));
299 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
300 utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000301 ConvertFunction ( &data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata8101f572015-07-17 01:56:25 +0000302 if (false == zero_is_terminator)
303 utf8_data_end_ptr = utf8_data_ptr;
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000304 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
305 }
306 else
307 {
308 // just copy the pointers - the cast is necessary to make the compiler happy
309 // but this should only happen if we are reading UTF8 data
310 utf8_data_ptr = (UTF8*)data_ptr;
311 utf8_data_end_ptr = (UTF8*)data_end_ptr;
312 }
313
Enrico Granatad07f7552015-07-17 01:03:59 +0000314 const bool escape_non_printables = dump_options.GetEscapeNonPrintables();
315
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000316 // since we tend to accept partial data (and even partially malformed data)
317 // we might end up with no NULL terminator before the end_ptr
318 // hence we need to take a slower route and ensure we stay within boundaries
319 for (;utf8_data_ptr < utf8_data_end_ptr;)
320 {
Enrico Granatad07f7552015-07-17 01:03:59 +0000321 if (zero_is_terminator && !*utf8_data_ptr)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000322 break;
323
Enrico Granatad07f7552015-07-17 01:03:59 +0000324 if (escape_non_printables)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000325 {
326 uint8_t* next_data = nullptr;
327 auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data);
328 auto printable_bytes = printable.GetBytes();
329 auto printable_size = printable.GetSize();
330 if (!printable_bytes || !next_data)
331 {
332 // GetPrintable() failed on us - print one byte in a desperate resync attempt
333 printable_bytes = utf8_data_ptr;
334 printable_size = 1;
335 next_data = utf8_data_ptr+1;
336 }
Andy Gibbs3acfe1a2014-12-29 13:03:19 +0000337 for (unsigned c = 0; c < printable_size; c++)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000338 stream.Printf("%c", *(printable_bytes+c));
339 utf8_data_ptr = (uint8_t*)next_data;
340 }
341 else
342 {
343 stream.Printf("%c",*utf8_data_ptr);
344 utf8_data_ptr++;
345 }
346 }
347 }
Enrico Granatad07f7552015-07-17 01:03:59 +0000348 if (dump_options.GetQuote() != 0)
349 stream.Printf("%c",dump_options.GetQuote());
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000350 return true;
351}
352
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000353lldb_private::formatters::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) :
354 ReadStringAndDumpToStreamOptions()
355{
356 SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
357}
358
359lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) :
360 ReadBufferAndDumpToStreamOptions()
361{
362 SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables());
363}
364
Enrico Granatad07f7552015-07-17 01:03:59 +0000365lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const lldb_private::formatters::ReadStringAndDumpToStreamOptions& options) :
366 ReadBufferAndDumpToStreamOptions()
367{
368 SetStream(options.GetStream());
369 SetPrefixToken(options.GetPrefixToken());
370 SetQuote(options.GetQuote());
371 SetEscapeNonPrintables(options.GetEscapeNonPrintables());
372 SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator());
373}
374
Enrico Granataebdc1ac2014-11-05 21:20:48 +0000375
Shawn Bestfd137432014-11-04 22:43:34 +0000376namespace lldb_private
377{
378
379namespace formatters
380{
381
382template <>
383bool
Enrico Granataad650a12015-09-09 20:59:49 +0000384StringPrinter::ReadStringAndDumpToStream<StringElementType::ASCII> (const ReadStringAndDumpToStreamOptions& options)
Shawn Bestfd137432014-11-04 22:43:34 +0000385{
386 assert(options.GetStream() && "need a Stream to print the string to");
387 Error my_error;
Shawn Bestfd137432014-11-04 22:43:34 +0000388
389 ProcessSP process_sp(options.GetProcessSP());
390
391 if (process_sp.get() == nullptr || options.GetLocation() == 0)
392 return false;
393
394 size_t size;
395
396 if (options.GetSourceSize() == 0)
397 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
Enrico Granata34042212014-11-18 22:54:45 +0000398 else if (!options.GetIgnoreMaxLength())
Shawn Bestfd137432014-11-04 22:43:34 +0000399 size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granata34042212014-11-18 22:54:45 +0000400 else
401 size = options.GetSourceSize();
Shawn Bestfd137432014-11-04 22:43:34 +0000402
403 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
404
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000405 process_sp->ReadCStringFromMemory(options.GetLocation(), (char*)buffer_sp->GetBytes(), size, my_error);
Shawn Bestfd137432014-11-04 22:43:34 +0000406
407 if (my_error.Fail())
408 return false;
409
410 char prefix_token = options.GetPrefixToken();
411 char quote = options.GetQuote();
412
413 if (prefix_token != 0)
414 options.GetStream()->Printf("%c%c",prefix_token,quote);
415 else if (quote != 0)
416 options.GetStream()->Printf("%c",quote);
417
418 uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize();
419
420 // since we tend to accept partial data (and even partially malformed data)
421 // we might end up with no NULL terminator before the end_ptr
422 // hence we need to take a slower route and ensure we stay within boundaries
423 for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);)
424 {
425 if (options.GetEscapeNonPrintables())
426 {
427 uint8_t* next_data = nullptr;
428 auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data);
429 auto printable_bytes = printable.GetBytes();
430 auto printable_size = printable.GetSize();
431 if (!printable_bytes || !next_data)
432 {
433 // GetPrintable() failed on us - print one byte in a desperate resync attempt
434 printable_bytes = data;
435 printable_size = 1;
436 next_data = data+1;
437 }
Andy Gibbs3acfe1a2014-12-29 13:03:19 +0000438 for (unsigned c = 0; c < printable_size; c++)
Shawn Bestfd137432014-11-04 22:43:34 +0000439 options.GetStream()->Printf("%c", *(printable_bytes+c));
440 data = (uint8_t*)next_data;
441 }
442 else
443 {
444 options.GetStream()->Printf("%c",*data);
445 data++;
446 }
447 }
448
449 if (quote != 0)
450 options.GetStream()->Printf("%c",quote);
451
452 return true;
453}
454
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000455template<typename SourceDataType>
456static bool
457ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options,
458 ConversionResult (*ConvertFunction) (const SourceDataType**,
459 const SourceDataType*,
460 UTF8**,
461 UTF8*,
462 ConversionFlags))
463{
464 assert(options.GetStream() && "need a Stream to print the string to");
465
466 if (options.GetLocation() == 0 || options.GetLocation() == LLDB_INVALID_ADDRESS)
467 return false;
Shawn Bestfd137432014-11-04 22:43:34 +0000468
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000469 lldb::ProcessSP process_sp(options.GetProcessSP());
Shawn Bestfd137432014-11-04 22:43:34 +0000470
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000471 if (!process_sp)
472 return false;
Shawn Bestfd137432014-11-04 22:43:34 +0000473
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000474 const int type_width = sizeof(SourceDataType);
475 const int origin_encoding = 8 * type_width ;
476 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
477 return false;
478 // if not UTF8, I need a conversion function to return proper UTF8
479 if (origin_encoding != 8 && !ConvertFunction)
480 return false;
Shawn Bestfd137432014-11-04 22:43:34 +0000481
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000482 if (!options.GetStream())
483 return false;
Shawn Bestfd137432014-11-04 22:43:34 +0000484
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000485 uint32_t sourceSize = options.GetSourceSize();
486 bool needs_zero_terminator = options.GetNeedsZeroTermination();
Shawn Bestfd137432014-11-04 22:43:34 +0000487
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000488 if (!sourceSize)
489 {
490 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
491 needs_zero_terminator = true;
492 }
Enrico Granatab0e8a552015-05-01 22:57:38 +0000493 else if (!options.GetIgnoreMaxLength())
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000494 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Shawn Bestfd137432014-11-04 22:43:34 +0000495
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000496 const int bufferSPSize = sourceSize * type_width;
Shawn Bestfd137432014-11-04 22:43:34 +0000497
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000498 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
Shawn Bestfd137432014-11-04 22:43:34 +0000499
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000500 if (!buffer_sp->GetBytes())
501 return false;
Shawn Bestfd137432014-11-04 22:43:34 +0000502
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000503 Error error;
504 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
Shawn Bestfd137432014-11-04 22:43:34 +0000505
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000506 if (needs_zero_terminator)
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000507 process_sp->ReadStringFromMemory(options.GetLocation(), buffer, bufferSPSize, error, type_width);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000508 else
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000509 process_sp->ReadMemoryFromInferior(options.GetLocation(), (char*)buffer_sp->GetBytes(), bufferSPSize, error);
Shawn Bestfd137432014-11-04 22:43:34 +0000510
Enrico Granata099263b2014-11-17 23:14:11 +0000511 if (error.Fail())
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000512 {
513 options.GetStream()->Printf("unable to read data");
514 return true;
515 }
Shawn Bestfd137432014-11-04 22:43:34 +0000516
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000517 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
Enrico Granatad07f7552015-07-17 01:03:59 +0000518
519 ReadBufferAndDumpToStreamOptions dump_options(options);
520 dump_options.SetData(data);
521 dump_options.SetSourceSize(sourceSize);
Shawn Bestfd137432014-11-04 22:43:34 +0000522
Enrico Granatad07f7552015-07-17 01:03:59 +0000523 return DumpUTFBufferToStream(ConvertFunction, dump_options);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000524}
525
526template <>
527bool
Enrico Granataad650a12015-09-09 20:59:49 +0000528StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8> (const ReadStringAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000529{
530 return ReadUTFBufferAndDumpToStream<UTF8>(options,
531 nullptr);
532}
533
534template <>
535bool
Enrico Granataad650a12015-09-09 20:59:49 +0000536StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF16> (const ReadStringAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000537{
538 return ReadUTFBufferAndDumpToStream<UTF16>(options,
539 ConvertUTF16toUTF8);
540}
541
542template <>
543bool
Enrico Granataad650a12015-09-09 20:59:49 +0000544StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF32> (const ReadStringAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000545{
546 return ReadUTFBufferAndDumpToStream<UTF32>(options,
547 ConvertUTF32toUTF8);
548}
549
550template <>
551bool
Enrico Granataad650a12015-09-09 20:59:49 +0000552StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF8> (const ReadBufferAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000553{
554 assert(options.GetStream() && "need a Stream to print the string to");
555
Enrico Granatad07f7552015-07-17 01:03:59 +0000556 return DumpUTFBufferToStream<UTF8>(nullptr, options);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000557}
558
559template <>
560bool
Enrico Granataad650a12015-09-09 20:59:49 +0000561StringPrinter::ReadBufferAndDumpToStream<StringElementType::ASCII> (const ReadBufferAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000562{
563 // treat ASCII the same as UTF8
564 // FIXME: can we optimize ASCII some more?
565 return ReadBufferAndDumpToStream<StringElementType::UTF8>(options);
566}
567
568template <>
569bool
Enrico Granataad650a12015-09-09 20:59:49 +0000570StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF16> (const ReadBufferAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000571{
572 assert(options.GetStream() && "need a Stream to print the string to");
Shawn Bestfd137432014-11-04 22:43:34 +0000573
Enrico Granatad07f7552015-07-17 01:03:59 +0000574 return DumpUTFBufferToStream(ConvertUTF16toUTF8, options);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000575}
576
577template <>
578bool
Enrico Granataad650a12015-09-09 20:59:49 +0000579StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF32> (const ReadBufferAndDumpToStreamOptions& options)
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000580{
581 assert(options.GetStream() && "need a Stream to print the string to");
Shawn Bestfd137432014-11-04 22:43:34 +0000582
Enrico Granatad07f7552015-07-17 01:03:59 +0000583 return DumpUTFBufferToStream(ConvertUTF32toUTF8, options);
Enrico Granataca6c8ee2014-10-30 01:45:39 +0000584}
Shawn Bestfd137432014-11-04 22:43:34 +0000585
586} // namespace formatters
587
588} // namespace lldb_private