blob: f74b4de567e54eb6b5b1db368033c8e5db84756a [file] [log] [blame]
Enrico Granatacaaf0102012-09-04 18:48:21 +00001//===-- CXXFormatterFunctions.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
Enrico Granataf509c5e2013-01-28 23:47:25 +000010#include "lldb/DataFormatters/CXXFormatterFunctions.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000011
Dmitri Gribenko2a64f9a2013-01-30 15:05:59 +000012#include "llvm/Support/ConvertUTF.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000013
Enrico Granataf91e78f2012-09-13 18:27:09 +000014#include "lldb/Core/DataBufferHeap.h"
15#include "lldb/Core/Error.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000016#include "lldb/Core/Stream.h"
17#include "lldb/Core/ValueObject.h"
Enrico Granataf91e78f2012-09-13 18:27:09 +000018#include "lldb/Core/ValueObjectConstResult.h"
19#include "lldb/Host/Endian.h"
Enrico Granatadb054912012-10-29 21:18:03 +000020#include "lldb/Symbol/ClangASTContext.h"
Enrico Granatacaaf0102012-09-04 18:48:21 +000021#include "lldb/Target/ObjCLanguageRuntime.h"
22#include "lldb/Target/Target.h"
23
Enrico Granatafb1493d2013-04-02 21:25:34 +000024#include <algorithm>
25
Enrico Granatacaaf0102012-09-04 18:48:21 +000026using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::formatters;
29
30bool
Enrico Granataf91e78f2012-09-13 18:27:09 +000031lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
32 const char* target_type,
33 const char* selector,
34 uint64_t &value)
Enrico Granatacaaf0102012-09-04 18:48:21 +000035{
36 if (!target_type || !*target_type)
37 return false;
38 if (!selector || !*selector)
39 return false;
Enrico Granatacaaf0102012-09-04 18:48:21 +000040 StreamString expr;
Daniel Maleab9db9d52012-12-07 22:21:08 +000041 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granatacaaf0102012-09-04 18:48:21 +000042 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
43 lldb::ValueObjectSP result_sp;
44 Target* target = exe_ctx.GetTargetPtr();
45 StackFrame* stack_frame = exe_ctx.GetFramePtr();
46 if (!target || !stack_frame)
47 return false;
Enrico Granatad27026e2012-09-05 20:41:26 +000048
Jim Ingham47beabb2012-10-16 21:41:58 +000049 EvaluateExpressionOptions options;
Enrico Granatad27026e2012-09-05 20:41:26 +000050 options.SetCoerceToId(false)
51 .SetUnwindOnError(true)
Sean Callanan99611fe2012-12-04 20:56:04 +000052 .SetKeepInMemory(true);
Enrico Granatad27026e2012-09-05 20:41:26 +000053
Enrico Granatacaaf0102012-09-04 18:48:21 +000054 target->EvaluateExpression(expr.GetData(),
55 stack_frame,
Enrico Granatad27026e2012-09-05 20:41:26 +000056 result_sp,
57 options);
Enrico Granatacaaf0102012-09-04 18:48:21 +000058 if (!result_sp)
59 return false;
60 value = result_sp->GetValueAsUnsigned(0);
61 return true;
62}
63
Enrico Granataea687532013-02-15 23:38:37 +000064bool
65lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
66 const char* target_type,
67 const char* selector,
68 Stream &stream)
69{
70 if (!target_type || !*target_type)
71 return false;
72 if (!selector || !*selector)
73 return false;
74 StreamString expr;
Enrico Granata04d3bb22013-02-19 01:14:06 +000075 expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector);
Enrico Granataea687532013-02-15 23:38:37 +000076 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
77 lldb::ValueObjectSP result_sp;
78 Target* target = exe_ctx.GetTargetPtr();
79 StackFrame* stack_frame = exe_ctx.GetFramePtr();
80 if (!target || !stack_frame)
81 return false;
82
83 EvaluateExpressionOptions options;
84 options.SetCoerceToId(false)
85 .SetUnwindOnError(true)
86 .SetKeepInMemory(true)
87 .SetUseDynamic(lldb::eDynamicCanRunTarget);
88
89 target->EvaluateExpression(expr.GetData(),
90 stack_frame,
91 result_sp,
92 options);
93 if (!result_sp)
94 return false;
95 stream.Printf("%s",result_sp->GetSummaryAsCString());
96 return true;
97}
98
Enrico Granataf91e78f2012-09-13 18:27:09 +000099lldb::ValueObjectSP
100lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
101 const char* return_type,
102 const char* selector,
103 uint64_t index)
104{
105 lldb::ValueObjectSP valobj_sp;
106 if (!return_type || !*return_type)
107 return valobj_sp;
108 if (!selector || !*selector)
109 return valobj_sp;
110 StreamString expr_path_stream;
111 valobj.GetExpressionPath(expr_path_stream, false);
112 StreamString expr;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000113 expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index);
Enrico Granataf91e78f2012-09-13 18:27:09 +0000114 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
115 lldb::ValueObjectSP result_sp;
116 Target* target = exe_ctx.GetTargetPtr();
117 StackFrame* stack_frame = exe_ctx.GetFramePtr();
118 if (!target || !stack_frame)
119 return valobj_sp;
120
Jim Ingham47beabb2012-10-16 21:41:58 +0000121 EvaluateExpressionOptions options;
Enrico Granataf91e78f2012-09-13 18:27:09 +0000122 options.SetCoerceToId(false)
123 .SetUnwindOnError(true)
124 .SetKeepInMemory(true)
125 .SetUseDynamic(lldb::eDynamicCanRunTarget);
126
127 target->EvaluateExpression(expr.GetData(),
128 stack_frame,
129 valobj_sp,
130 options);
131 return valobj_sp;
132}
133
134lldb::ValueObjectSP
135lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
136 const char* return_type,
137 const char* selector,
138 const char* key)
139{
140 lldb::ValueObjectSP valobj_sp;
141 if (!return_type || !*return_type)
142 return valobj_sp;
143 if (!selector || !*selector)
144 return valobj_sp;
145 if (!key || !*key)
146 return valobj_sp;
147 StreamString expr_path_stream;
148 valobj.GetExpressionPath(expr_path_stream, false);
149 StreamString expr;
150 expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key);
151 ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
152 lldb::ValueObjectSP result_sp;
153 Target* target = exe_ctx.GetTargetPtr();
154 StackFrame* stack_frame = exe_ctx.GetFramePtr();
155 if (!target || !stack_frame)
156 return valobj_sp;
157
Jim Ingham47beabb2012-10-16 21:41:58 +0000158 EvaluateExpressionOptions options;
Enrico Granataf91e78f2012-09-13 18:27:09 +0000159 options.SetCoerceToId(false)
160 .SetUnwindOnError(true)
161 .SetKeepInMemory(true)
162 .SetUseDynamic(lldb::eDynamicCanRunTarget);
163
164 target->EvaluateExpression(expr.GetData(),
165 stack_frame,
166 valobj_sp,
167 options);
168 return valobj_sp;
169}
170
Enrico Granatacd8cd612013-01-14 23:53:26 +0000171// use this call if you already have an LLDB-side buffer for the data
172template<typename SourceDataType>
Enrico Granataf5545f92013-01-10 22:08:35 +0000173static bool
Enrico Granatacd8cd612013-01-14 23:53:26 +0000174DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
175 const SourceDataType*,
176 UTF8**,
177 UTF8*,
178 ConversionFlags),
179 DataExtractor& data,
180 Stream& stream,
181 char prefix_token = '@',
182 char quote = '"',
Enrico Granatafb1493d2013-04-02 21:25:34 +0000183 uint32_t sourceSize = 0)
Enrico Granataf5545f92013-01-10 22:08:35 +0000184{
Enrico Granatacd8cd612013-01-14 23:53:26 +0000185 if (prefix_token != 0)
186 stream.Printf("%c",prefix_token);
187 if (quote != 0)
188 stream.Printf("%c",quote);
189 if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd())
Enrico Granataf5545f92013-01-10 22:08:35 +0000190 {
Enrico Granatacd8cd612013-01-14 23:53:26 +0000191 const int bufferSPSize = data.GetByteSize();
192 if (sourceSize == 0)
193 {
194 const int origin_encoding = 8*sizeof(SourceDataType);
Greg Clayton0cd33402013-02-08 21:59:34 +0000195 sourceSize = bufferSPSize/(origin_encoding / 4);
Enrico Granatacd8cd612013-01-14 23:53:26 +0000196 }
197
198 SourceDataType *data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf5545f92013-01-10 22:08:35 +0000199 SourceDataType *data_end_ptr = data_ptr + sourceSize;
200
201 while (data_ptr < data_end_ptr)
202 {
203 if (!*data_ptr)
204 {
205 data_end_ptr = data_ptr;
206 break;
207 }
208 data_ptr++;
209 }
210
Enrico Granatacd8cd612013-01-14 23:53:26 +0000211 data_ptr = (SourceDataType*)data.GetDataStart();
Enrico Granataf5545f92013-01-10 22:08:35 +0000212
Enrico Granata06d58b02013-01-11 02:44:00 +0000213 lldb::DataBufferSP utf8_data_buffer_sp;
214 UTF8* utf8_data_ptr = nullptr;
215 UTF8* utf8_data_end_ptr = nullptr;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000216
Enrico Granataf5545f92013-01-10 22:08:35 +0000217 if (ConvertFunction)
Enrico Granata06d58b02013-01-11 02:44:00 +0000218 {
219 utf8_data_buffer_sp.reset(new DataBufferHeap(bufferSPSize,0));
220 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes();
221 utf8_data_end_ptr = utf8_data_ptr + bufferSPSize;
Enrico Granataf5545f92013-01-10 22:08:35 +0000222 ConvertFunction ( (const SourceDataType**)&data_ptr, data_end_ptr, &utf8_data_ptr, utf8_data_end_ptr, lenientConversion );
Enrico Granata06d58b02013-01-11 02:44:00 +0000223 utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr
224 }
Enrico Granataf5545f92013-01-10 22:08:35 +0000225 else
226 {
227 // just copy the pointers - the cast is necessary to make the compiler happy
228 // but this should only happen if we are reading UTF8 data
229 utf8_data_ptr = (UTF8*)data_ptr;
230 utf8_data_end_ptr = (UTF8*)data_end_ptr;
231 }
232
Enrico Granatab6985792013-01-12 01:00:22 +0000233 // since we tend to accept partial data (and even partially malformed data)
234 // we might end up with no NULL terminator before the end_ptr
235 // hence we need to take a slower route and ensure we stay within boundaries
Enrico Granataf5545f92013-01-10 22:08:35 +0000236 for (;utf8_data_ptr != utf8_data_end_ptr; utf8_data_ptr++)
237 {
238 if (!*utf8_data_ptr)
239 break;
240 stream.Printf("%c",*utf8_data_ptr);
241 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000242 }
243 if (quote != 0)
244 stream.Printf("%c",quote);
245 return true;
246}
247
248template<typename SourceDataType>
249static bool
250ReadUTFBufferAndDumpToStream (ConversionResult (*ConvertFunction) (const SourceDataType**,
251 const SourceDataType*,
252 UTF8**,
253 UTF8*,
254 ConversionFlags),
255 uint64_t location,
256 const ProcessSP& process_sp,
257 Stream& stream,
258 char prefix_token = '@',
259 char quote = '"',
Enrico Granatafb1493d2013-04-02 21:25:34 +0000260 uint32_t sourceSize = 0)
Enrico Granatacd8cd612013-01-14 23:53:26 +0000261{
262 if (location == 0 || location == LLDB_INVALID_ADDRESS)
263 return false;
264 if (!process_sp)
265 return false;
266
Ashok Thirumurthi347d7222013-04-19 15:58:38 +0000267 const int type_width = sizeof(SourceDataType);
268 const int origin_encoding = 8 * type_width ;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000269 if (origin_encoding != 8 && origin_encoding != 16 && origin_encoding != 32)
270 return false;
271 // if not UTF8, I need a conversion function to return proper UTF8
272 if (origin_encoding != 8 && !ConvertFunction)
273 return false;
274
Enrico Granata54f30202013-04-02 23:07:55 +0000275 if (!sourceSize)
276 sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
277 else
278 sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
279
Ashok Thirumurthi347d7222013-04-19 15:58:38 +0000280 const int bufferSPSize = sourceSize * type_width;
Enrico Granatacd8cd612013-01-14 23:53:26 +0000281
Enrico Granatacd8cd612013-01-14 23:53:26 +0000282 lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize,0));
283
284 if (!buffer_sp->GetBytes())
285 return false;
286
Ashok Thirumurthi347d7222013-04-19 15:58:38 +0000287 Error error;
288 char *buffer = reinterpret_cast<char *>(buffer_sp->GetBytes());
289
290 size_t data_read = process_sp->ReadStringFromMemory(location, buffer, bufferSPSize, error, type_width);
Enrico Granatacd8cd612013-01-14 23:53:26 +0000291 if (error.Fail() || data_read == 0)
292 {
293 stream.Printf("unable to read data");
Enrico Granataf5545f92013-01-10 22:08:35 +0000294 return true;
295 }
Enrico Granatacd8cd612013-01-14 23:53:26 +0000296
297 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
298
299 return DumpUTFBufferToStream(ConvertFunction, data, stream, prefix_token, quote, sourceSize);
Enrico Granataf5545f92013-01-10 22:08:35 +0000300}
301
302bool
303lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream)
304{
305 ProcessSP process_sp = valobj.GetProcessSP();
306 if (!process_sp)
307 return false;
308
309 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
310
311 if (!valobj_addr)
312 return false;
313
Enrico Granatacd8cd612013-01-14 23:53:26 +0000314 if (!ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000315 process_sp,
316 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000317 'u'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000318 {
319 stream.Printf("Summary Unavailable");
320 return true;
321 }
322
323 return true;
324}
325
326bool
327lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream)
328{
329 ProcessSP process_sp = valobj.GetProcessSP();
330 if (!process_sp)
331 return false;
332
333 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
334
335 if (!valobj_addr)
336 return false;
337
Enrico Granatacd8cd612013-01-14 23:53:26 +0000338 if (!ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8,valobj_addr,
Enrico Granataf5545f92013-01-10 22:08:35 +0000339 process_sp,
340 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000341 'U'))
Enrico Granataf5545f92013-01-10 22:08:35 +0000342 {
343 stream.Printf("Summary Unavailable");
344 return true;
345 }
346
347 return true;
348}
349
350bool
351lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream)
352{
Enrico Granata06d58b02013-01-11 02:44:00 +0000353 ProcessSP process_sp = valobj.GetProcessSP();
354 if (!process_sp)
355 return false;
356
Enrico Granatab6985792013-01-12 01:00:22 +0000357 lldb::addr_t data_addr = 0;
358
359 if (valobj.IsPointerType())
360 data_addr = valobj.GetValueAsUnsigned(0);
361 else if (valobj.IsArrayType())
362 data_addr = valobj.GetAddressOf();
Enrico Granata06d58b02013-01-11 02:44:00 +0000363
Enrico Granatab6985792013-01-12 01:00:22 +0000364 if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS)
Enrico Granata06d58b02013-01-11 02:44:00 +0000365 return false;
366
367 clang::ASTContext* ast = valobj.GetClangAST();
368
369 if (!ast)
370 return false;
371
372 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
373
374 switch (wchar_size)
375 {
376 case 8:
377 // utf 8
Enrico Granatacd8cd612013-01-14 23:53:26 +0000378 return ReadUTFBufferAndDumpToStream<UTF8>(nullptr, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000379 process_sp,
380 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000381 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000382 case 16:
383 // utf 16
Enrico Granatacd8cd612013-01-14 23:53:26 +0000384 return ReadUTFBufferAndDumpToStream<UTF16>(ConvertUTF16toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000385 process_sp,
386 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000387 'L');
Enrico Granata06d58b02013-01-11 02:44:00 +0000388 case 32:
389 // utf 32
Enrico Granatacd8cd612013-01-14 23:53:26 +0000390 return ReadUTFBufferAndDumpToStream<UTF32>(ConvertUTF32toUTF8, data_addr,
Enrico Granata06d58b02013-01-11 02:44:00 +0000391 process_sp,
392 stream,
Enrico Granatacd8cd612013-01-14 23:53:26 +0000393 'L');
394 default:
395 stream.Printf("size for wchar_t is not valid");
396 return true;
397 }
398 return true;
399}
400
401bool
402lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream)
403{
404 DataExtractor data;
405 valobj.GetData(data);
406
407 std::string value;
408 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
409 if (!value.empty())
410 stream.Printf("%s ", value.c_str());
411
412 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,data,stream, 'u','\'',1);
413}
414
415bool
416lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream)
417{
418 DataExtractor data;
419 valobj.GetData(data);
420
421 std::string value;
422 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
423 if (!value.empty())
424 stream.Printf("%s ", value.c_str());
425
426 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,data,stream, 'U','\'',1);
427}
428
429bool
430lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream)
431{
432 DataExtractor data;
433 valobj.GetData(data);
434
435 clang::ASTContext* ast = valobj.GetClangAST();
436
437 if (!ast)
438 return false;
439
440 std::string value;
441
442 uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType());
443
444 switch (wchar_size)
445 {
446 case 8:
447 // utf 8
448 valobj.GetValueAsCString(lldb::eFormatChar, value);
449 if (!value.empty())
450 stream.Printf("%s ", value.c_str());
451 return DumpUTFBufferToStream<UTF8>(nullptr,
452 data,
453 stream,
454 'L',
455 '\'',
456 1);
457 case 16:
458 // utf 16
459 valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
460 if (!value.empty())
461 stream.Printf("%s ", value.c_str());
462 return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8,
463 data,
464 stream,
465 'L',
466 '\'',
467 1);
468 case 32:
469 // utf 32
470 valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
471 if (!value.empty())
472 stream.Printf("%s ", value.c_str());
473 return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8,
474 data,
475 stream,
476 'L',
477 '\'',
478 1);
Enrico Granata06d58b02013-01-11 02:44:00 +0000479 default:
480 stream.Printf("size for wchar_t is not valid");
481 return true;
482 }
483 return true;
Enrico Granataf5545f92013-01-10 22:08:35 +0000484}
485
Enrico Granatab6985792013-01-12 01:00:22 +0000486// this function extracts information from a libcxx std::basic_string<>
487// irregardless of template arguments. it reports the size (in item count not bytes)
488// and the location in memory where the string data can be found
489static bool
490ExtractLibcxxStringInfo (ValueObject& valobj,
491 ValueObjectSP &location_sp,
492 uint64_t& size)
493{
494 ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
495 if (!D)
496 return false;
497
498 ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
499 if (!size_mode)
500 return false;
501
502 uint64_t size_mode_value(size_mode->GetValueAsUnsigned(0));
503
504 if ((size_mode_value & 1) == 0) // this means the string is in short-mode and the data is stored inline
505 {
506 ValueObjectSP s(D->GetChildAtIndex(1, true));
507 if (!s)
508 return false;
509 size = ((size_mode_value >> 1) % 256);
510 location_sp = s->GetChildAtIndex(1, true);
511 return (location_sp.get() != nullptr);
512 }
513 else
514 {
515 ValueObjectSP l(D->GetChildAtIndex(0, true));
516 if (!l)
517 return false;
518 location_sp = l->GetChildAtIndex(2, true);
519 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
520 if (!size_vo || !location_sp)
521 return false;
522 size = size_vo->GetValueAsUnsigned(0);
523 return true;
524 }
525}
526
527bool
528lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream)
529{
530 uint64_t size = 0;
531 ValueObjectSP location_sp((ValueObject*)nullptr);
532 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
533 return false;
534 if (size == 0)
535 {
536 stream.Printf("L\"\"");
537 return true;
538 }
539 if (!location_sp)
540 return false;
541 return WCharStringSummaryProvider(*location_sp.get(), stream);
542}
543
544bool
545lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream)
546{
547 uint64_t size = 0;
548 ValueObjectSP location_sp((ValueObject*)nullptr);
549 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
550 return false;
551 if (size == 0)
552 {
553 stream.Printf("\"\"");
554 return true;
555 }
556 if (!location_sp)
557 return false;
558 Error error;
Enrico Granata32d7ee32013-02-21 19:57:10 +0000559 if (location_sp->ReadPointedString(stream,
560 error,
561 0, // max length is decided by the settings
562 false) == 0) // do not honor array (terminates on first 0 byte even for a char[])
563 stream.Printf("\"\""); // if nothing was read, print an empty string
Enrico Granatab6985792013-01-12 01:00:22 +0000564 return error.Success();
565}
566
Enrico Granata280b30f2013-03-15 18:55:30 +0000567bool
568lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream)
569{
570 ProcessSP process_sp = valobj.GetProcessSP();
571 if (!process_sp)
572 return false;
573
574 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
575
576 if (!runtime)
577 return false;
578
Greg Claytond387b462013-04-19 21:31:16 +0000579 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
Enrico Granata280b30f2013-03-15 18:55:30 +0000580
581 if (!descriptor.get() || !descriptor->IsValid())
582 return false;
583
584 const char* class_name = descriptor->GetClassName().GetCString();
585
586 if (!class_name || !*class_name)
587 return false;
588
589 stream.Printf("%s",class_name);
590 return true;
591}
592
Enrico Granatacaaf0102012-09-04 18:48:21 +0000593template<bool needs_at>
594bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000595lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000596{
597 ProcessSP process_sp = valobj.GetProcessSP();
598 if (!process_sp)
599 return false;
600
601 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
602
603 if (!runtime)
604 return false;
605
606 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
607
608 if (!descriptor.get() || !descriptor->IsValid())
609 return false;
610
611 bool is_64bit = (process_sp->GetAddressByteSize() == 8);
612 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
613
614 if (!valobj_addr)
615 return false;
616
617 uint64_t value = 0;
618
619 const char* class_name = descriptor->GetClassName().GetCString();
Enrico Granata7685a562012-09-29 00:47:43 +0000620
621 if (!class_name || !*class_name)
622 return false;
623
Enrico Granatacaaf0102012-09-04 18:48:21 +0000624 if (!strcmp(class_name,"NSConcreteData") ||
625 !strcmp(class_name,"NSConcreteMutableData") ||
626 !strcmp(class_name,"__NSCFData"))
627 {
628 uint32_t offset = (is_64bit ? 16 : 8);
629 Error error;
630 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
631 if (error.Fail())
632 return false;
633 }
634 else
635 {
Enrico Granataf91e78f2012-09-13 18:27:09 +0000636 if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
Enrico Granatacaaf0102012-09-04 18:48:21 +0000637 return false;
638 }
639
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000640 stream.Printf("%s%" PRIu64 " byte%s%s",
Enrico Granatacaaf0102012-09-04 18:48:21 +0000641 (needs_at ? "@\"" : ""),
642 value,
643 (value > 1 ? "s" : ""),
644 (needs_at ? "\"" : ""));
645
646 return true;
647}
648
Enrico Granataf3a217e2013-02-21 20:31:18 +0000649static bool
650ReadAsciiBufferAndDumpToStream (lldb::addr_t location,
651 lldb::ProcessSP& process_sp,
652 Stream& dest,
Enrico Granatafb1493d2013-04-02 21:25:34 +0000653 uint32_t size = 0,
Enrico Granataf3a217e2013-02-21 20:31:18 +0000654 Error* error = NULL,
655 size_t *data_read = NULL,
656 char prefix_token = '@',
657 char quote = '"')
658{
659 Error my_error;
660 size_t my_data_read;
661 if (!process_sp || location == 0)
662 return false;
663
Enrico Granata54f30202013-04-02 23:07:55 +0000664 if (!size)
665 size = process_sp->GetTarget().GetMaximumSizeOfStringSummary();
666 else
667 size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary());
Enrico Granataf3a217e2013-02-21 20:31:18 +0000668
669 lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0));
670
671 my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error);
672
673 if (error)
674 *error = my_error;
675 if (data_read)
676 *data_read = my_data_read;
677
678 if (my_error.Fail())
679 return false;
680 if (my_data_read)
681 dest.Printf("%c%c%s%c",prefix_token,quote,(char*)buffer_sp->GetBytes(),quote);
682
683 return true;
684}
685
Enrico Granatafb1493d2013-04-02 21:25:34 +0000686#ifdef WANT_DEEP_PRINT
687struct lldb__notInlineMutable {
688 void *buffer;
689 signed long length;
690 signed long capacity;
691 unsigned int hasGap:1;
692 unsigned int isFixedCapacity:1;
693 unsigned int isExternalMutable:1;
694 unsigned int capacityProvidedExternally:1;
695#if __LP64__
696 unsigned long desiredCapacity:60;
697#else
698 unsigned long desiredCapacity:28;
699#endif
700 void* contentsAllocator;
701};
702
703struct lldb__CFString {
704 uintptr_t _cfisa;
705 uint8_t _cfinfo[4];
706 uint32_t _rc;
707 union {
708 struct __inline1 {
709 signed long length;
710 } inline1;
711 struct __notInlineImmutable1 {
712 void *buffer;
713 signed long length;
714 void* contentsDeallocator;
715 } notInlineImmutable1;
716 struct __notInlineImmutable2 {
717 void *buffer;
718 void* contentsDeallocator;
719 } notInlineImmutable2;
720 struct lldb__notInlineMutable notInlineMutable;
721 } variants;
722};
723#endif
724
Enrico Granatacaaf0102012-09-04 18:48:21 +0000725bool
Enrico Granataf91e78f2012-09-13 18:27:09 +0000726lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream)
Enrico Granatacaaf0102012-09-04 18:48:21 +0000727{
728 ProcessSP process_sp = valobj.GetProcessSP();
729 if (!process_sp)
730 return false;
731
732 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
733
734 if (!runtime)
735 return false;
736
737 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
738
739 if (!descriptor.get() || !descriptor->IsValid())
740 return false;
741
742 uint32_t ptr_size = process_sp->GetAddressByteSize();
743
744 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
745
746 if (!valobj_addr)
747 return false;
748
749 const char* class_name = descriptor->GetClassName().GetCString();
750
Enrico Granata25c9ade2012-09-29 00:45:53 +0000751 if (!class_name || !*class_name)
752 return false;
753
Enrico Granatacaaf0102012-09-04 18:48:21 +0000754 uint64_t info_bits_location = valobj_addr + ptr_size;
755 if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
756 info_bits_location += 3;
757
Enrico Granataf3a217e2013-02-21 20:31:18 +0000758 Error error;
Enrico Granatacaaf0102012-09-04 18:48:21 +0000759
760 uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
761 if (error.Fail())
762 return false;
763
764 bool is_mutable = (info_bits & 1) == 1;
765 bool is_inline = (info_bits & 0x60) == 0;
766 bool has_explicit_length = (info_bits & (1 | 4)) != 4;
767 bool is_unicode = (info_bits & 0x10) == 0x10;
768 bool is_special = strcmp(class_name,"NSPathStore2") == 0;
Enrico Granatafb1493d2013-04-02 21:25:34 +0000769 bool has_null = (info_bits & 8) == 8;
770
771 size_t explicit_length = 0;
772 if (!has_null && has_explicit_length && !is_special)
773 {
774 lldb::addr_t explicit_length_offset = 2*ptr_size;
775 if (is_mutable and not is_inline)
776 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
777 else if (is_inline)
778 explicit_length = explicit_length + 0; // inline1.length;
779 else if (not is_inline and not is_mutable)
780 explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
781 else
782 explicit_length_offset = 0;
783
784 if (explicit_length_offset)
785 {
786 explicit_length_offset = valobj_addr + explicit_length_offset;
787 explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
788 }
789 }
790
791#ifdef WANT_DEEP_PRINT
792 lldb__CFString my_string_data;
793 process_sp->ReadMemory(valobj_addr, &my_string_data, sizeof(lldb__CFString),error);
794
795 printf(R"(
796 __CFString my_string_data = {
797 uintptr_t _cfisa = %lu
798 uint8_t _cfinfo[4] = %c%c%c%c
799 uint32_t _rc = %d
800 union {
801 struct __inline1 {
802 signed long length = %ld
803 } inline1;
804 struct __notInlineImmutable1 {
805 void *buffer = %p
806 signed long length = %ld
807 void* contentsDeallocator = %p
808 } notInlineImmutable1;
809 struct __notInlineImmutable2 {
810 void *buffer = %p
811 void* contentsDeallocator = %p
812 } notInlineImmutable2;
813 struct __notInlineMutable notInlineMutable {
814 void *buffer = %p
815 signed long length = %ld
816 signed long capacity = %ld
817 unsigned int hasGap:1 = %d
818 unsigned int isFixedCapacity:1 = %d
819 unsigned int isExternalMutable:1 = %d
820 unsigned int capacityProvidedExternally:1 = %d
821#if __LP64__
822 unsigned long desiredCapacity:60 = %lu
823#else
824 unsigned long desiredCapacity:28 = %lu
825#endif
826 void* contentsAllocator = %p
827 }
828 } variants;
829 };\n)",
830 my_string_data._cfisa,
831 my_string_data._cfinfo[0],my_string_data._cfinfo[1],my_string_data._cfinfo[2],my_string_data._cfinfo[3],
832 my_string_data._rc,
833 my_string_data.variants.inline1.length,
834 my_string_data.variants.notInlineImmutable1.buffer,
835 my_string_data.variants.notInlineImmutable1.length,
836 my_string_data.variants.notInlineImmutable1.contentsDeallocator,
837 my_string_data.variants.notInlineImmutable2.buffer,
838 my_string_data.variants.notInlineImmutable2.contentsDeallocator,
839 my_string_data.variants.notInlineMutable.buffer,
840 my_string_data.variants.notInlineMutable.length,
841 my_string_data.variants.notInlineMutable.capacity,
842 my_string_data.variants.notInlineMutable.hasGap,
843 my_string_data.variants.notInlineMutable.isFixedCapacity,
844 my_string_data.variants.notInlineMutable.isExternalMutable,
845 my_string_data.variants.notInlineMutable.capacityProvidedExternally,
846 my_string_data.variants.notInlineMutable.desiredCapacity,
847 my_string_data.variants.notInlineMutable.desiredCapacity,
848 my_string_data.variants.notInlineMutable.contentsAllocator);
849#endif
Enrico Granatacaaf0102012-09-04 18:48:21 +0000850
851 if (strcmp(class_name,"NSString") &&
852 strcmp(class_name,"CFStringRef") &&
853 strcmp(class_name,"CFMutableStringRef") &&
854 strcmp(class_name,"__NSCFConstantString") &&
855 strcmp(class_name,"__NSCFString") &&
856 strcmp(class_name,"NSCFConstantString") &&
857 strcmp(class_name,"NSCFString") &&
858 strcmp(class_name,"NSPathStore2"))
859 {
Enrico Granataf3a217e2013-02-21 20:31:18 +0000860 // not one of us - but tell me class name
861 stream.Printf("class name = %s",class_name);
862 return true;
Enrico Granatacaaf0102012-09-04 18:48:21 +0000863 }
864
Enrico Granatafb1493d2013-04-02 21:25:34 +0000865#ifdef WANT_DEEP_PRNT
866 stream.Printf("(M:%dI:%dL:%zuU:%dS:%dN:%d) ",
867 is_mutable,
868 is_inline,
869 explicit_length,
870 is_unicode,
871 is_special,
872 has_null);
873#endif
874
Enrico Granatacaaf0102012-09-04 18:48:21 +0000875 if (is_mutable)
876 {
877 uint64_t location = 2 * ptr_size + valobj_addr;
878 location = process_sp->ReadPointerFromMemory(location, error);
879 if (error.Fail())
880 return false;
881 if (has_explicit_length and is_unicode)
Enrico Granatafb1493d2013-04-02 21:25:34 +0000882 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8,location, process_sp, stream, '@', '"', explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000883 else
Enrico Granatafb1493d2013-04-02 21:25:34 +0000884 return ReadAsciiBufferAndDumpToStream(location+1,process_sp,stream, explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000885 }
886 else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable)
887 {
888 uint64_t location = 3 * ptr_size + valobj_addr;
Enrico Granatafb1493d2013-04-02 21:25:34 +0000889 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000890 }
891 else if (is_unicode)
892 {
Enrico Granataf3a217e2013-02-21 20:31:18 +0000893 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granatacaaf0102012-09-04 18:48:21 +0000894 if (is_inline)
895 {
896 if (!has_explicit_length)
897 {
898 stream.Printf("found new combo");
899 return true;
900 }
901 else
902 location += ptr_size;
903 }
904 else
905 {
906 location = process_sp->ReadPointerFromMemory(location, error);
907 if (error.Fail())
908 return false;
909 }
Enrico Granatafb1493d2013-04-02 21:25:34 +0000910 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@', '"', explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000911 }
912 else if (is_special)
913 {
914 uint64_t location = valobj_addr + (ptr_size == 8 ? 12 : 8);
Enrico Granatafb1493d2013-04-02 21:25:34 +0000915 return ReadUTFBufferAndDumpToStream<UTF16> (ConvertUTF16toUTF8, location, process_sp, stream, '@', '"', explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000916 }
917 else if (is_inline)
918 {
Enrico Granataf3a217e2013-02-21 20:31:18 +0000919 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granatacaaf0102012-09-04 18:48:21 +0000920 if (!has_explicit_length)
921 location++;
Enrico Granatafb1493d2013-04-02 21:25:34 +0000922 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000923 }
924 else
925 {
Enrico Granataf3a217e2013-02-21 20:31:18 +0000926 uint64_t location = valobj_addr + 2*ptr_size;
Enrico Granatacaaf0102012-09-04 18:48:21 +0000927 location = process_sp->ReadPointerFromMemory(location, error);
928 if (error.Fail())
929 return false;
Enrico Granatafb1493d2013-04-02 21:25:34 +0000930 return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length);
Enrico Granatacaaf0102012-09-04 18:48:21 +0000931 }
932
933 stream.Printf("class name = %s",class_name);
934 return true;
935
936}
937
Enrico Granata9abbfba2012-10-03 23:53:45 +0000938bool
Enrico Granatadcffc1a2013-02-08 01:55:46 +0000939lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
940{
941 TargetSP target_sp(valobj.GetTargetSP());
942 if (!target_sp)
943 return false;
944 uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
945 uint64_t pointee = valobj.GetValueAsUnsigned(0);
946 if (!pointee)
947 return false;
948 pointee += addr_size;
949 ClangASTType type(valobj.GetClangAST(),valobj.GetClangType());
950 ExecutionContext exe_ctx(target_sp,false);
951 ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointee, exe_ctx, type));
952 if (!child_ptr_sp)
953 return false;
954 DataExtractor data;
955 child_ptr_sp->GetData(data);
956 ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
957 child_sp->GetValueAsUnsigned(0);
958 if (child_sp)
959 return NSStringSummaryProvider(*child_sp, stream);
960 return false;
961}
962
963bool
964lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream)
965{
966 return NSAttributedStringSummaryProvider(valobj, stream);
967}
968
969bool
Enrico Granata9abbfba2012-10-03 23:53:45 +0000970lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream)
971{
972 stream.Printf("%s",valobj.GetObjectDescription());
973 return true;
974}
975
Enrico Granatadb054912012-10-29 21:18:03 +0000976bool
977lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream)
978{
979 const uint32_t type_info = ClangASTContext::GetTypeInfo(valobj.GetClangType(),
980 valobj.GetClangAST(),
981 NULL);
982
983 ValueObjectSP real_guy_sp = valobj.GetSP();
984
985 if (type_info & ClangASTContext::eTypeIsPointer)
986 {
987 Error err;
988 real_guy_sp = valobj.Dereference(err);
989 if (err.Fail() || !real_guy_sp)
990 return false;
991 }
992 else if (type_info & ClangASTContext::eTypeIsReference)
993 {
994 real_guy_sp = valobj.GetChildAtIndex(0, true);
995 if (!real_guy_sp)
996 return false;
997 }
998 uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
999 if (value == 0)
1000 {
1001 stream.Printf("NO");
1002 return true;
1003 }
1004 stream.Printf("YES");
1005 return true;
1006}
1007
1008template <bool is_sel_ptr>
1009bool
1010lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream)
1011{
Enrico Granata1f9df782013-02-15 00:06:04 +00001012 lldb::ValueObjectSP valobj_sp;
Enrico Granatadb054912012-10-29 21:18:03 +00001013
Enrico Granata1f9df782013-02-15 00:06:04 +00001014 if (!valobj.GetClangAST())
Enrico Granatadb054912012-10-29 21:18:03 +00001015 return false;
Enrico Granata1f9df782013-02-15 00:06:04 +00001016 void* char_opaque_type = valobj.GetClangAST()->CharTy.getAsOpaquePtr();
1017 if (!char_opaque_type)
1018 return false;
1019 ClangASTType charstar(valobj.GetClangAST(),ClangASTType::GetPointerType(valobj.GetClangAST(), char_opaque_type));
1020
Enrico Granatadb054912012-10-29 21:18:03 +00001021 ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1022
Enrico Granata1f9df782013-02-15 00:06:04 +00001023 if (is_sel_ptr)
1024 {
1025 lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
1026 if (data_address == LLDB_INVALID_ADDRESS)
1027 return false;
1028 valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
1029 }
1030 else
1031 {
1032 DataExtractor data;
1033 valobj.GetData(data);
1034 valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
1035 }
Enrico Granatadb054912012-10-29 21:18:03 +00001036
Enrico Granata1f9df782013-02-15 00:06:04 +00001037 if (!valobj_sp)
1038 return false;
Enrico Granatadb054912012-10-29 21:18:03 +00001039
1040 stream.Printf("%s",valobj_sp->GetSummaryAsCString());
1041 return true;
1042}
1043
Enrico Granatacba09f62013-03-19 00:27:22 +00001044// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
1045// this call gives the POSIX equivalent of the Cocoa epoch
1046time_t
Enrico Granatacc5d2742013-03-19 22:58:48 +00001047lldb_private::formatters::GetOSXEpoch ()
Enrico Granatacba09f62013-03-19 00:27:22 +00001048{
1049 static time_t epoch = 0;
1050 if (!epoch)
1051 {
1052 tzset();
1053 tm tm_epoch;
1054 tm_epoch.tm_sec = 0;
1055 tm_epoch.tm_hour = 0;
1056 tm_epoch.tm_min = 0;
1057 tm_epoch.tm_mon = 0;
1058 tm_epoch.tm_mday = 1;
1059 tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
1060 tm_epoch.tm_isdst = -1;
1061 tm_epoch.tm_gmtoff = 0;
1062 tm_epoch.tm_zone = NULL;
1063 epoch = timegm(&tm_epoch);
1064 }
1065 return epoch;
1066}
1067
Greg Clayton36da2aa2013-01-25 18:06:21 +00001068size_t
Enrico Granataea687532013-02-15 23:38:37 +00001069lldb_private::formatters::ExtractIndexFromString (const char* item_name)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001070{
1071 if (!item_name || !*item_name)
1072 return UINT32_MAX;
1073 if (*item_name != '[')
1074 return UINT32_MAX;
1075 item_name++;
Enrico Granataea687532013-02-15 23:38:37 +00001076 char* endptr = NULL;
1077 unsigned long int idx = ::strtoul(item_name, &endptr, 0);
1078 if (idx == 0 && endptr == item_name)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001079 return UINT32_MAX;
Enrico Granataea687532013-02-15 23:38:37 +00001080 if (idx == ULONG_MAX)
Enrico Granataf91e78f2012-09-13 18:27:09 +00001081 return UINT32_MAX;
1082 return idx;
1083}
1084
Enrico Granata32d7ee32013-02-21 19:57:10 +00001085lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
1086 ConstString item_name) :
Enrico Granata689696c2013-02-04 22:54:42 +00001087SyntheticChildrenFrontEnd(*valobj_sp.get()),
1088m_exe_ctx_ref(),
Enrico Granata32d7ee32013-02-21 19:57:10 +00001089m_item_name(item_name),
1090m_item_sp()
Enrico Granata689696c2013-02-04 22:54:42 +00001091{
1092 if (valobj_sp)
1093 Update();
Enrico Granata689696c2013-02-04 22:54:42 +00001094}
1095
Enrico Granata689696c2013-02-04 22:54:42 +00001096bool
Enrico Granata32d7ee32013-02-21 19:57:10 +00001097lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
Enrico Granata689696c2013-02-04 22:54:42 +00001098{
Enrico Granatad32acdb2013-03-28 18:50:54 +00001099 m_item_sp.reset();
1100
Enrico Granata689696c2013-02-04 22:54:42 +00001101 ValueObjectSP valobj_sp = m_backend.GetSP();
1102 if (!valobj_sp)
1103 return false;
Enrico Granata32d7ee32013-02-21 19:57:10 +00001104
Enrico Granata689696c2013-02-04 22:54:42 +00001105 if (!valobj_sp)
1106 return false;
Enrico Granata32d7ee32013-02-21 19:57:10 +00001107
1108 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
1109 if (!item_ptr)
1110 return false;
1111 if (item_ptr->GetValueAsUnsigned(0) == 0)
1112 return false;
1113 Error err;
Enrico Granata689696c2013-02-04 22:54:42 +00001114 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
Enrico Granata32d7ee32013-02-21 19:57:10 +00001115 m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType())));
1116 if (err.Fail())
1117 m_item_sp.reset();
Enrico Granatad32acdb2013-03-28 18:50:54 +00001118 return false;
Enrico Granata32d7ee32013-02-21 19:57:10 +00001119}
Enrico Granata689696c2013-02-04 22:54:42 +00001120
Enrico Granata32d7ee32013-02-21 19:57:10 +00001121size_t
1122lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
1123{
1124 return 1;
1125}
Enrico Granata689696c2013-02-04 22:54:42 +00001126
Enrico Granata32d7ee32013-02-21 19:57:10 +00001127lldb::ValueObjectSP
1128lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
1129{
1130 if (idx == 0)
1131 return m_item_sp;
1132 return lldb::ValueObjectSP();
Enrico Granata689696c2013-02-04 22:54:42 +00001133}
1134
1135bool
Enrico Granata32d7ee32013-02-21 19:57:10 +00001136lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granata689696c2013-02-04 22:54:42 +00001137{
1138 return true;
1139}
1140
1141size_t
Enrico Granata32d7ee32013-02-21 19:57:10 +00001142lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granata689696c2013-02-04 22:54:42 +00001143{
Enrico Granata32d7ee32013-02-21 19:57:10 +00001144 if (name == ConstString("item"))
1145 return 0;
1146 return UINT32_MAX;
Enrico Granata689696c2013-02-04 22:54:42 +00001147}
1148
Enrico Granata32d7ee32013-02-21 19:57:10 +00001149lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
Enrico Granata689696c2013-02-04 22:54:42 +00001150{
Enrico Granata689696c2013-02-04 22:54:42 +00001151}
1152
Enrico Granatacaaf0102012-09-04 18:48:21 +00001153template bool
Enrico Granataf91e78f2012-09-13 18:27:09 +00001154lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&) ;
1155
1156template bool
1157lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&) ;
Enrico Granatadb054912012-10-29 21:18:03 +00001158
1159template bool
1160lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&) ;
1161
1162template bool
1163lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&) ;