@@ -114,58 +114,91 @@ class ListIterator {
114
114
ListEntry m_entry;
115
115
};
116
116
117
- } // end anonymous namespace
118
-
119
- namespace lldb_private {
120
- namespace formatters {
121
- class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
117
+ class AbstractListFrontEnd : public SyntheticChildrenFrontEnd {
122
118
public:
123
- LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
119
+ size_t GetIndexOfChildWithName (const ConstString &name) override {
120
+ return ExtractIndexFromString (name.GetCString ());
121
+ }
122
+ bool MightHaveChildren () override { return true ; }
123
+ bool Update () override ;
124
124
125
- ~LibcxxStdListSyntheticFrontEnd () override = default ;
125
+ protected:
126
+ AbstractListFrontEnd (ValueObject &valobj)
127
+ : SyntheticChildrenFrontEnd(valobj) {}
126
128
127
- size_t CalculateNumChildren () override ;
129
+ size_t m_count;
130
+ ValueObject *m_head;
128
131
129
- lldb::ValueObjectSP GetChildAtIndex (size_t idx) override ;
132
+ static constexpr bool g_use_loop_detect = true ;
133
+ size_t m_loop_detected; // The number of elements that have had loop detection
134
+ // run over them.
135
+ ListEntry m_slow_runner; // Used for loop detection
136
+ ListEntry m_fast_runner; // Used for loop detection
137
+
138
+ size_t m_list_capping_size;
139
+ CompilerType m_element_type;
140
+ std::map<size_t , ListIterator> m_iterators;
141
+
142
+ bool HasLoop (size_t count);
143
+ ValueObjectSP GetItem (size_t idx);
144
+ };
130
145
146
+ class ForwardListFrontEnd : public AbstractListFrontEnd {
147
+ public:
148
+ ForwardListFrontEnd (ValueObject &valobj);
149
+
150
+ size_t CalculateNumChildren () override ;
151
+ ValueObjectSP GetChildAtIndex (size_t idx) override ;
131
152
bool Update () override ;
153
+ };
132
154
133
- bool MightHaveChildren () override ;
155
+ class ListFrontEnd : public AbstractListFrontEnd {
156
+ public:
157
+ ListFrontEnd (lldb::ValueObjectSP valobj_sp);
134
158
135
- size_t GetIndexOfChildWithName ( const ConstString &name ) override ;
159
+ ~ListFrontEnd ( ) override = default ;
136
160
137
- private:
138
- bool HasLoop (size_t count);
161
+ size_t CalculateNumChildren () override ;
139
162
140
- size_t m_list_capping_size;
141
- static const bool g_use_loop_detect = true ;
163
+ lldb::ValueObjectSP GetChildAtIndex (size_t idx) override ;
142
164
143
- size_t m_loop_detected; // The number of elements that have had loop detection
144
- // run over them.
145
- ListEntry m_slow_runner; // Used for loop detection
146
- ListEntry m_fast_runner; // Used for loop detection
165
+ bool Update () override ;
147
166
167
+ private:
148
168
lldb::addr_t m_node_address;
149
- ValueObject *m_head;
150
169
ValueObject *m_tail;
151
- CompilerType m_element_type;
152
- size_t m_count;
153
- std::map<size_t , ListIterator> m_iterators;
154
170
};
155
- } // namespace formatters
156
- } // namespace lldb_private
157
-
158
- lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::
159
- LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp)
160
- : SyntheticChildrenFrontEnd(*valobj_sp), m_list_capping_size(0 ),
161
- m_loop_detected(0 ), m_node_address(), m_head(nullptr ), m_tail(nullptr ),
162
- m_element_type(), m_count(UINT32_MAX), m_iterators() {
163
- if (valobj_sp)
164
- Update ();
171
+
172
+ } // end anonymous namespace
173
+
174
+ bool AbstractListFrontEnd::Update () {
175
+ m_loop_detected = 0 ;
176
+ m_count = UINT32_MAX;
177
+ m_head = nullptr ;
178
+ m_list_capping_size = 0 ;
179
+ m_slow_runner.SetEntry (nullptr );
180
+ m_fast_runner.SetEntry (nullptr );
181
+ m_iterators.clear ();
182
+
183
+ if (m_backend.GetTargetSP ())
184
+ m_list_capping_size =
185
+ m_backend.GetTargetSP ()->GetMaximumNumberOfChildrenToDisplay ();
186
+ if (m_list_capping_size == 0 )
187
+ m_list_capping_size = 255 ;
188
+
189
+ CompilerType list_type = m_backend.GetCompilerType ();
190
+ if (list_type.IsReferenceType ())
191
+ list_type = list_type.GetNonReferenceType ();
192
+
193
+ if (list_type.GetNumTemplateArguments () == 0 )
194
+ return false ;
195
+ TemplateArgumentKind kind;
196
+ m_element_type = list_type.GetTemplateArgument (0 , kind);
197
+
198
+ return false ;
165
199
}
166
200
167
- bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop (
168
- size_t count) {
201
+ bool AbstractListFrontEnd::HasLoop (size_t count) {
169
202
if (!g_use_loop_detect)
170
203
return false ;
171
204
// don't bother checking for a loop if we won't actually need to jump nodes
@@ -201,8 +234,96 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(
201
234
return m_slow_runner == m_fast_runner;
202
235
}
203
236
204
- size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::
205
- CalculateNumChildren () {
237
+ ValueObjectSP AbstractListFrontEnd::GetItem (size_t idx) {
238
+ size_t advance = idx;
239
+ ListIterator current (m_head);
240
+ if (idx > 0 ) {
241
+ auto cached_iterator = m_iterators.find (idx - 1 );
242
+ if (cached_iterator != m_iterators.end ()) {
243
+ current = cached_iterator->second ;
244
+ advance = 1 ;
245
+ }
246
+ }
247
+ ValueObjectSP value_sp = current.advance (advance);
248
+ m_iterators[idx] = current;
249
+ return value_sp;
250
+ }
251
+
252
+ ForwardListFrontEnd::ForwardListFrontEnd (ValueObject &valobj)
253
+ : AbstractListFrontEnd(valobj) {
254
+ Update ();
255
+ }
256
+
257
+ size_t ForwardListFrontEnd::CalculateNumChildren () {
258
+ if (m_count != UINT32_MAX)
259
+ return m_count;
260
+
261
+ ListEntry current (m_head);
262
+ m_count = 0 ;
263
+ while (current && m_count < m_list_capping_size) {
264
+ ++m_count;
265
+ current = current.next ();
266
+ }
267
+ return m_count;
268
+ }
269
+
270
+ ValueObjectSP ForwardListFrontEnd::GetChildAtIndex (size_t idx) {
271
+ if (idx >= CalculateNumChildren ())
272
+ return nullptr ;
273
+
274
+ if (!m_head)
275
+ return nullptr ;
276
+
277
+ if (HasLoop (idx + 1 ))
278
+ return nullptr ;
279
+
280
+ ValueObjectSP current_sp = GetItem (idx);
281
+ if (!current_sp)
282
+ return nullptr ;
283
+
284
+ current_sp = current_sp->GetChildAtIndex (1 , true ); // get the __value_ child
285
+ if (!current_sp)
286
+ return nullptr ;
287
+
288
+ // we need to copy current_sp into a new object otherwise we will end up with
289
+ // all items named __value_
290
+ DataExtractor data;
291
+ Status error;
292
+ current_sp->GetData (data, error);
293
+ if (error.Fail ())
294
+ return nullptr ;
295
+
296
+ return CreateValueObjectFromData (llvm::formatv (" [{0}]" , idx).str (), data,
297
+ m_backend.GetExecutionContextRef (),
298
+ m_element_type);
299
+ }
300
+
301
+ bool ForwardListFrontEnd::Update () {
302
+ AbstractListFrontEnd::Update ();
303
+
304
+ Status err;
305
+ ValueObjectSP backend_addr (m_backend.AddressOf (err));
306
+ if (err.Fail () || !backend_addr)
307
+ return false ;
308
+
309
+ ValueObjectSP impl_sp (
310
+ m_backend.GetChildMemberWithName (ConstString (" __before_begin_" ), true ));
311
+ if (!impl_sp)
312
+ return false ;
313
+ impl_sp = impl_sp->GetChildMemberWithName (ConstString (" __first_" ), true );
314
+ if (!impl_sp)
315
+ return false ;
316
+ m_head = impl_sp->GetChildMemberWithName (ConstString (" __next_" ), true ).get ();
317
+ return false ;
318
+ }
319
+
320
+ ListFrontEnd::ListFrontEnd (lldb::ValueObjectSP valobj_sp)
321
+ : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr ) {
322
+ if (valobj_sp)
323
+ Update ();
324
+ }
325
+
326
+ size_t ListFrontEnd::CalculateNumChildren () {
206
327
if (m_count != UINT32_MAX)
207
328
return m_count;
208
329
if (!m_head || !m_tail || m_node_address == 0 )
@@ -239,9 +360,7 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::
239
360
}
240
361
}
241
362
242
- lldb::ValueObjectSP
243
- lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (
244
- size_t idx) {
363
+ lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex (size_t idx) {
245
364
static ConstString g_value (" __value_" );
246
365
static ConstString g_next (" __next_" );
247
366
@@ -254,23 +373,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex(
254
373
if (HasLoop (idx + 1 ))
255
374
return lldb::ValueObjectSP ();
256
375
257
- size_t actual_advance = idx;
258
-
259
- ListIterator current (m_head);
260
- if (idx > 0 ) {
261
- auto cached_iterator = m_iterators.find (idx - 1 );
262
- if (cached_iterator != m_iterators.end ()) {
263
- current = cached_iterator->second ;
264
- actual_advance = 1 ;
265
- }
266
- }
267
-
268
- ValueObjectSP current_sp (current.advance (actual_advance));
376
+ ValueObjectSP current_sp = GetItem (idx);
269
377
if (!current_sp)
270
378
return lldb::ValueObjectSP ();
271
379
272
- m_iterators[idx] = current;
273
-
274
380
current_sp = current_sp->GetChildAtIndex (1 , true ); // get the __value_ child
275
381
if (!current_sp)
276
382
return lldb::ValueObjectSP ();
@@ -303,23 +409,13 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex(
303
409
m_element_type);
304
410
}
305
411
306
- bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd ::Update () {
307
- m_iterators. clear ();
308
- m_head = m_tail = nullptr ;
412
+ bool ListFrontEnd ::Update () {
413
+ AbstractListFrontEnd::Update ();
414
+ m_tail = nullptr ;
309
415
m_node_address = 0 ;
310
- m_count = UINT32_MAX;
311
- m_loop_detected = 0 ;
312
- m_slow_runner.SetEntry (nullptr );
313
- m_fast_runner.SetEntry (nullptr );
314
416
315
417
Status err;
316
418
ValueObjectSP backend_addr (m_backend.AddressOf (err));
317
- m_list_capping_size = 0 ;
318
- if (m_backend.GetTargetSP ())
319
- m_list_capping_size =
320
- m_backend.GetTargetSP ()->GetMaximumNumberOfChildrenToDisplay ();
321
- if (m_list_capping_size == 0 )
322
- m_list_capping_size = 255 ;
323
419
if (err.Fail () || !backend_addr)
324
420
return false ;
325
421
m_node_address = backend_addr->GetValueAsUnsigned (0 );
@@ -329,31 +425,18 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() {
329
425
m_backend.GetChildMemberWithName (ConstString (" __end_" ), true ));
330
426
if (!impl_sp)
331
427
return false ;
332
- CompilerType list_type = m_backend.GetCompilerType ();
333
- if (list_type.IsReferenceType ())
334
- list_type = list_type.GetNonReferenceType ();
335
-
336
- if (list_type.GetNumTemplateArguments () == 0 )
337
- return false ;
338
- lldb::TemplateArgumentKind kind;
339
- m_element_type = list_type.GetTemplateArgument (0 , kind);
340
428
m_head = impl_sp->GetChildMemberWithName (ConstString (" __next_" ), true ).get ();
341
429
m_tail = impl_sp->GetChildMemberWithName (ConstString (" __prev_" ), true ).get ();
342
430
return false ;
343
431
}
344
432
345
- bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::
346
- MightHaveChildren () {
347
- return true ;
348
- }
349
-
350
- size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::
351
- GetIndexOfChildWithName (const ConstString &name) {
352
- return ExtractIndexFromString (name.GetCString ());
433
+ SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator (
434
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
435
+ return (valobj_sp ? new ListFrontEnd (valobj_sp) : nullptr );
353
436
}
354
437
355
438
SyntheticChildrenFrontEnd *
356
- lldb_private:: formatters::LibcxxStdListSyntheticFrontEndCreator (
439
+ formatters::LibcxxStdForwardListSyntheticFrontEndCreator (
357
440
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
358
- return ( valobj_sp ? new LibcxxStdListSyntheticFrontEnd ( valobj_sp) : nullptr ) ;
441
+ return valobj_sp ? new ForwardListFrontEnd (* valobj_sp) : nullptr ;
359
442
}
0 commit comments