1 /*
2 * Copyright 2012-2015, Rene Gollent, rene@gollent.com
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "BListValueNode.h"
8
9 #include <new>
10
11 #include <AutoDeleter.h>
12
13 #include "AddressValueNode.h"
14 #include "Architecture.h"
15 #include "StringValue.h"
16 #include "TeamTypeInformation.h"
17 #include "Tracing.h"
18 #include "Type.h"
19 #include "TypeLookupConstraints.h"
20 #include "ValueLoader.h"
21 #include "ValueLocation.h"
22 #include "ValueNodeContainer.h"
23
24
25 // maximum number of array elements to show by default
26 static const int64 kMaxArrayElementCount = 20;
27
28
29 //#pragma mark - BListValueNode::BListElementNodeChild
30
31
32 class BListValueNode::BListElementNodeChild : public ValueNodeChild {
33 public:
34 BListElementNodeChild(BListValueNode* parent,
35 int64 elementIndex, Type* type);
36 virtual ~BListElementNodeChild();
37
Name() const38 virtual const BString& Name() const { return fName; };
GetType() const39 virtual Type* GetType() const { return fType; };
Parent() const40 virtual ValueNode* Parent() const { return fParent; };
41
42 virtual status_t ResolveLocation(ValueLoader* valueLoader,
43 ValueLocation*& _location);
44
45 private:
46 Type* fType;
47 BListValueNode* fParent;
48 int64 fElementIndex;
49 BString fName;
50 };
51
52
BListElementNodeChild(BListValueNode * parent,int64 elementIndex,Type * type)53 BListValueNode::BListElementNodeChild::BListElementNodeChild(
54 BListValueNode* parent, int64 elementIndex, Type* type)
55 :
56 ValueNodeChild(),
57 fType(type),
58 fParent(parent),
59 fElementIndex(elementIndex),
60 fName()
61 {
62 fType->AcquireReference();
63 fParent->AcquireReference();
64 fName.SetToFormat("[%" B_PRId64 "]", fElementIndex);
65 }
66
67
~BListElementNodeChild()68 BListValueNode::BListElementNodeChild::~BListElementNodeChild()
69 {
70 fType->ReleaseReference();
71 fParent->ReleaseReference();
72 }
73
74
75 status_t
ResolveLocation(ValueLoader * valueLoader,ValueLocation * & _location)76 BListValueNode::BListElementNodeChild::ResolveLocation(
77 ValueLoader* valueLoader, ValueLocation*& _location)
78 {
79 uint8 addressSize = valueLoader->GetArchitecture()->AddressSize();
80 ValueLocation* location = new(std::nothrow) ValueLocation();
81 if (location == NULL)
82 return B_NO_MEMORY;
83
84
85 uint64 listAddress = fParent->fDataLocation.ToUInt64();
86 listAddress += fElementIndex * addressSize;
87
88 ValuePieceLocation piece;
89 piece.SetToMemory(listAddress);
90 piece.SetSize(addressSize);
91 location->AddPiece(piece);
92
93 _location = location;
94 return B_OK;
95 }
96
97
98 //#pragma mark - BListItemCountNodeChild
99
100 class BListValueNode::BListItemCountNodeChild : public ValueNodeChild {
101 public:
102 BListItemCountNodeChild(BVariant location,
103 BListValueNode* parent, Type* type);
104 virtual ~BListItemCountNodeChild();
105
Name() const106 virtual const BString& Name() const { return fName; };
GetType() const107 virtual Type* GetType() const { return fType; };
Parent() const108 virtual ValueNode* Parent() const { return fParent; };
109
110 virtual status_t ResolveLocation(ValueLoader* valueLoader,
111 ValueLocation*& _location);
112
113 private:
114 Type* fType;
115 BListValueNode* fParent;
116 BVariant fLocation;
117 BString fName;
118 };
119
120
BListItemCountNodeChild(BVariant location,BListValueNode * parent,Type * type)121 BListValueNode::BListItemCountNodeChild::BListItemCountNodeChild(
122 BVariant location, BListValueNode* parent, Type* type)
123 :
124 ValueNodeChild(),
125 fType(type),
126 fParent(parent),
127 fLocation(location),
128 fName("Capacity")
129 {
130 fType->AcquireReference();
131 fParent->AcquireReference();
132 }
133
134
~BListItemCountNodeChild()135 BListValueNode::BListItemCountNodeChild::~BListItemCountNodeChild()
136 {
137 fType->ReleaseReference();
138 fParent->ReleaseReference();
139 }
140
141
142 status_t
ResolveLocation(ValueLoader * valueLoader,ValueLocation * & _location)143 BListValueNode::BListItemCountNodeChild::ResolveLocation(
144 ValueLoader* valueLoader, ValueLocation*& _location)
145 {
146 ValueLocation* location = new(std::nothrow) ValueLocation();
147 if (location == NULL)
148 return B_NO_MEMORY;
149
150 ValuePieceLocation piece;
151 piece.SetToMemory(fLocation.ToUInt64());
152 piece.SetSize(sizeof(int32));
153 location->AddPiece(piece);
154
155 _location = location;
156 return B_OK;
157 }
158
159
160 //#pragma mark - BListValueNode
161
BListValueNode(ValueNodeChild * nodeChild,Type * type)162 BListValueNode::BListValueNode(ValueNodeChild* nodeChild,
163 Type* type)
164 :
165 ValueNode(nodeChild),
166 fType(type),
167 fItemCountType(NULL),
168 fItemCount(0),
169 fCountChildCreated(false)
170 {
171 fType->AcquireReference();
172 }
173
174
~BListValueNode()175 BListValueNode::~BListValueNode()
176 {
177 fType->ReleaseReference();
178 for (int32 i = 0; i < fChildren.CountItems(); i++)
179 fChildren.ItemAt(i)->ReleaseReference();
180
181 if (fItemCountType != NULL)
182 fItemCountType->ReleaseReference();
183 }
184
185
186 Type*
GetType() const187 BListValueNode::GetType() const
188 {
189 return fType;
190 }
191
192
193 status_t
ResolvedLocationAndValue(ValueLoader * valueLoader,ValueLocation * & _location,Value * & _value)194 BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
195 ValueLocation*& _location, Value*& _value)
196 {
197 // get the location
198 ValueLocation* location = NodeChild()->Location();
199 if (location == NULL)
200 return B_BAD_VALUE;
201
202
203 // get the value type
204 type_code valueType;
205 if (valueLoader->GetArchitecture()->AddressSize() == 4) {
206 valueType = B_UINT32_TYPE;
207 TRACE_LOCALS(" -> 32 bit\n");
208 } else {
209 valueType = B_UINT64_TYPE;
210 TRACE_LOCALS(" -> 64 bit\n");
211 }
212
213 // load the value data
214
215 status_t error = B_OK;
216
217 ValueLocation* memberLocation = NULL;
218 CompoundType* baseType = dynamic_cast<CompoundType*>(fType);
219
220 if (baseType->CountTemplateParameters() != 0) {
221 // for BObjectList we need to walk up
222 // the hierarchy: BObjectList -> _PointerList_ -> BList
223 if (baseType->CountBaseTypes() == 0)
224 return B_BAD_DATA;
225
226 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
227 ->GetType());
228 if (baseType == NULL || baseType->Name() != "_PointerList_")
229 return B_BAD_DATA;
230
231 if (baseType->CountBaseTypes() == 0)
232 return B_BAD_DATA;
233
234 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
235 ->GetType());
236 if (baseType == NULL || baseType->Name() != "BList")
237 return B_BAD_DATA;
238
239 }
240
241 for (int32 i = 0; i < baseType->CountDataMembers(); i++) {
242 DataMember* member = baseType->DataMemberAt(i);
243 if (strcmp(member->Name(), "fObjectList") == 0) {
244 error = baseType->ResolveDataMemberLocation(member,
245 *location, memberLocation);
246 BReference<ValueLocation> locationRef(memberLocation, true);
247 if (error != B_OK) {
248 TRACE_LOCALS(
249 "BListValueNode::ResolvedLocationAndValue(): "
250 "failed to resolve location of header member: %s\n",
251 strerror(error));
252 return error;
253 }
254
255 error = valueLoader->LoadValue(memberLocation, valueType,
256 false, fDataLocation);
257 if (error != B_OK)
258 return error;
259 } else if (strcmp(member->Name(), "fItemCount") == 0) {
260 error = baseType->ResolveDataMemberLocation(member,
261 *location, memberLocation);
262 BReference<ValueLocation> locationRef(memberLocation, true);
263 if (error != B_OK) {
264 TRACE_LOCALS(
265 "BListValueNode::ResolvedLocationAndValue(): "
266 "failed to resolve location of header member: %s\n",
267 strerror(error));
268 return error;
269 }
270
271 fItemCountType = member->GetType();
272 fItemCountType->AcquireReference();
273
274 fItemCountLocation = memberLocation->PieceAt(0).address;
275
276 BVariant listSize;
277 error = valueLoader->LoadValue(memberLocation, B_INT32_TYPE,
278 false, listSize);
279 if (error != B_OK)
280 return error;
281
282 fItemCount = listSize.ToInt32();
283 TRACE_LOCALS(
284 "BListValueNode::ResolvedLocationAndValue(): "
285 "detected list size %" B_PRId32 "\n",
286 fItemCount);
287 }
288 memberLocation = NULL;
289 }
290
291 location->AcquireReference();
292 _location = location;
293 _value = NULL;
294
295 return B_OK;
296 }
297
298
299 status_t
CreateChildren(TeamTypeInformation * info)300 BListValueNode::CreateChildren(TeamTypeInformation* info)
301 {
302 return CreateChildrenInRange(info, 0, kMaxArrayElementCount);
303 }
304
305
306 int32
CountChildren() const307 BListValueNode::CountChildren() const
308 {
309 return fChildren.CountItems();
310 }
311
312
313 ValueNodeChild*
ChildAt(int32 index) const314 BListValueNode::ChildAt(int32 index) const
315 {
316 return fChildren.ItemAt(index);
317 }
318
319
320 bool
IsRangedContainer() const321 BListValueNode::IsRangedContainer() const
322 {
323 return true;
324 }
325
326
327 bool
IsContainerRangeFixed() const328 BListValueNode::IsContainerRangeFixed() const
329 {
330 return true;
331 }
332
333
334 void
ClearChildren()335 BListValueNode::ClearChildren()
336 {
337 fChildren.MakeEmpty();
338 fCountChildCreated = false;
339 if (fContainer != NULL)
340 fContainer->NotifyValueNodeChildrenDeleted(this);
341 }
342
343
344 status_t
CreateChildrenInRange(TeamTypeInformation * info,int32 lowIndex,int32 highIndex)345 BListValueNode::CreateChildrenInRange(TeamTypeInformation* info,
346 int32 lowIndex, int32 highIndex)
347 {
348 if (fLocationResolutionState != B_OK)
349 return fLocationResolutionState;
350
351 if (lowIndex < 0)
352 lowIndex = 0;
353 if (highIndex >= fItemCount)
354 highIndex = fItemCount - 1;
355
356 if (!fCountChildCreated && fItemCountType != NULL) {
357 BListItemCountNodeChild* countChild = new(std::nothrow)
358 BListItemCountNodeChild(fItemCountLocation, this, fItemCountType);
359
360 if (countChild == NULL)
361 return B_NO_MEMORY;
362
363 fCountChildCreated = true;
364 countChild->SetContainer(fContainer);
365 fChildren.AddItem(countChild);
366 }
367
368 BReference<Type> addressTypeRef;
369 Type* type = NULL;
370 CompoundType* objectType = dynamic_cast<CompoundType*>(fType);
371 if (objectType->CountTemplateParameters() != 0) {
372 AddressType* addressType = NULL;
373 status_t result = objectType->TemplateParameterAt(0)->GetType()
374 ->CreateDerivedAddressType(DERIVED_TYPE_POINTER, addressType);
375 if (result != B_OK)
376 return result;
377
378 type = addressType;
379 addressTypeRef.SetTo(type, true);
380 } else {
381 BString typeName;
382 TypeLookupConstraints constraints;
383 constraints.SetTypeKind(TYPE_ADDRESS);
384 constraints.SetBaseTypeName("void");
385 status_t result = info->LookupTypeByName(typeName, constraints,
386 type);
387 if (result != B_OK)
388 return result;
389 }
390
391 for (int32 i = lowIndex; i <= highIndex; i++)
392 {
393 BListElementNodeChild* child =
394 new(std::nothrow) BListElementNodeChild(this, i, type);
395 if (child == NULL)
396 return B_NO_MEMORY;
397 child->SetContainer(fContainer);
398 fChildren.AddItem(child);
399 }
400
401 fChildrenCreated = true;
402
403 if (fContainer != NULL)
404 fContainer->NotifyValueNodeChildrenCreated(this);
405
406 return B_OK;
407 }
408
409
410 status_t
SupportedChildRange(int32 & lowIndex,int32 & highIndex) const411 BListValueNode::SupportedChildRange(int32& lowIndex, int32& highIndex) const
412 {
413 lowIndex = 0;
414 highIndex = fItemCount - 1;
415
416 return B_OK;
417 }
418
419