Debugger: Split into core library and application.
[haiku.git] / src / kits / debugger / value / value_nodes / BListValueNode.cpp
blob4a5a52dedf148fb1ca39d7d05c340434136ced8e
1 /*
2 * Copyright 2012-2015, Rene Gollent, rene@gollent.com
3 * Distributed under the terms of the MIT License.
4 */
7 #include "BListValueNode.h"
9 #include <new>
11 #include <AutoDeleter.h>
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"
25 // maximum number of array elements to show by default
26 static const int64 kMaxArrayElementCount = 20;
29 //#pragma mark - BListValueNode::BListElementNodeChild
32 class BListValueNode::BListElementNodeChild : public ValueNodeChild {
33 public:
34 BListElementNodeChild(BListValueNode* parent,
35 int64 elementIndex, Type* type);
36 virtual ~BListElementNodeChild();
38 virtual const BString& Name() const { return fName; };
39 virtual Type* GetType() const { return fType; };
40 virtual ValueNode* Parent() const { return fParent; };
42 virtual status_t ResolveLocation(ValueLoader* valueLoader,
43 ValueLocation*& _location);
45 private:
46 Type* fType;
47 BListValueNode* fParent;
48 int64 fElementIndex;
49 BString fName;
53 BListValueNode::BListElementNodeChild::BListElementNodeChild(
54 BListValueNode* parent, int64 elementIndex, Type* type)
56 ValueNodeChild(),
57 fType(type),
58 fParent(parent),
59 fElementIndex(elementIndex),
60 fName()
62 fType->AcquireReference();
63 fParent->AcquireReference();
64 fName.SetToFormat("[%" B_PRId64 "]", fElementIndex);
68 BListValueNode::BListElementNodeChild::~BListElementNodeChild()
70 fType->ReleaseReference();
71 fParent->ReleaseReference();
75 status_t
76 BListValueNode::BListElementNodeChild::ResolveLocation(
77 ValueLoader* valueLoader, ValueLocation*& _location)
79 uint8 addressSize = valueLoader->GetArchitecture()->AddressSize();
80 ValueLocation* location = new(std::nothrow) ValueLocation();
81 if (location == NULL)
82 return B_NO_MEMORY;
85 uint64 listAddress = fParent->fDataLocation.ToUInt64();
86 listAddress += fElementIndex * addressSize;
88 ValuePieceLocation piece;
89 piece.SetToMemory(listAddress);
90 piece.SetSize(addressSize);
91 location->AddPiece(piece);
93 _location = location;
94 return B_OK;
98 //#pragma mark - BListItemCountNodeChild
100 class BListValueNode::BListItemCountNodeChild : public ValueNodeChild {
101 public:
102 BListItemCountNodeChild(BVariant location,
103 BListValueNode* parent, Type* type);
104 virtual ~BListItemCountNodeChild();
106 virtual const BString& Name() const { return fName; };
107 virtual Type* GetType() const { return fType; };
108 virtual ValueNode* Parent() const { return fParent; };
110 virtual status_t ResolveLocation(ValueLoader* valueLoader,
111 ValueLocation*& _location);
113 private:
114 Type* fType;
115 BListValueNode* fParent;
116 BVariant fLocation;
117 BString fName;
121 BListValueNode::BListItemCountNodeChild::BListItemCountNodeChild(
122 BVariant location, BListValueNode* parent, Type* type)
124 ValueNodeChild(),
125 fType(type),
126 fParent(parent),
127 fLocation(location),
128 fName("Capacity")
130 fType->AcquireReference();
131 fParent->AcquireReference();
135 BListValueNode::BListItemCountNodeChild::~BListItemCountNodeChild()
137 fType->ReleaseReference();
138 fParent->ReleaseReference();
142 status_t
143 BListValueNode::BListItemCountNodeChild::ResolveLocation(
144 ValueLoader* valueLoader, ValueLocation*& _location)
146 ValueLocation* location = new(std::nothrow) ValueLocation();
147 if (location == NULL)
148 return B_NO_MEMORY;
150 ValuePieceLocation piece;
151 piece.SetToMemory(fLocation.ToUInt64());
152 piece.SetSize(sizeof(int32));
153 location->AddPiece(piece);
155 _location = location;
156 return B_OK;
160 //#pragma mark - BListValueNode
162 BListValueNode::BListValueNode(ValueNodeChild* nodeChild,
163 Type* type)
165 ValueNode(nodeChild),
166 fType(type),
167 fItemCountType(NULL),
168 fItemCount(0),
169 fCountChildCreated(false)
171 fType->AcquireReference();
175 BListValueNode::~BListValueNode()
177 fType->ReleaseReference();
178 for (int32 i = 0; i < fChildren.CountItems(); i++)
179 fChildren.ItemAt(i)->ReleaseReference();
181 if (fItemCountType != NULL)
182 fItemCountType->ReleaseReference();
186 Type*
187 BListValueNode::GetType() const
189 return fType;
193 status_t
194 BListValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
195 ValueLocation*& _location, Value*& _value)
197 // get the location
198 ValueLocation* location = NodeChild()->Location();
199 if (location == NULL)
200 return B_BAD_VALUE;
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");
213 // load the value data
215 status_t error = B_OK;
216 _location = location;
217 _value = NULL;
219 ValueLocation* memberLocation = NULL;
220 CompoundType* baseType = dynamic_cast<CompoundType*>(fType);
222 if (baseType->CountTemplateParameters() != 0) {
223 // for BObjectList we need to walk up
224 // the hierarchy: BObjectList -> _PointerList_ -> BList
225 if (baseType->CountBaseTypes() == 0)
226 return B_BAD_DATA;
228 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
229 ->GetType());
230 if (baseType == NULL || baseType->Name() != "_PointerList_")
231 return B_BAD_DATA;
233 if (baseType->CountBaseTypes() == 0)
234 return B_BAD_DATA;
236 baseType = dynamic_cast<CompoundType*>(baseType->BaseTypeAt(0)
237 ->GetType());
238 if (baseType == NULL || baseType->Name() != "BList")
239 return B_BAD_DATA;
243 for (int32 i = 0; i < baseType->CountDataMembers(); i++) {
244 DataMember* member = baseType->DataMemberAt(i);
245 if (strcmp(member->Name(), "fObjectList") == 0) {
246 error = baseType->ResolveDataMemberLocation(member,
247 *location, memberLocation);
248 BReference<ValueLocation> locationRef(memberLocation, true);
249 if (error != B_OK) {
250 TRACE_LOCALS(
251 "BListValueNode::ResolvedLocationAndValue(): "
252 "failed to resolve location of header member: %s\n",
253 strerror(error));
254 return error;
257 error = valueLoader->LoadValue(memberLocation, valueType,
258 false, fDataLocation);
259 if (error != B_OK)
260 return error;
261 } else if (strcmp(member->Name(), "fItemCount") == 0) {
262 error = baseType->ResolveDataMemberLocation(member,
263 *location, memberLocation);
264 BReference<ValueLocation> locationRef(memberLocation, true);
265 if (error != B_OK) {
266 TRACE_LOCALS(
267 "BListValueNode::ResolvedLocationAndValue(): "
268 "failed to resolve location of header member: %s\n",
269 strerror(error));
270 return error;
273 fItemCountType = member->GetType();
274 fItemCountType->AcquireReference();
276 fItemCountLocation = memberLocation->PieceAt(0).address;
278 BVariant listSize;
279 error = valueLoader->LoadValue(memberLocation, valueType,
280 false, listSize);
281 if (error != B_OK)
282 return error;
284 fItemCount = listSize.ToInt32();
285 TRACE_LOCALS(
286 "BListValueNode::ResolvedLocationAndValue(): "
287 "detected list size %" B_PRId32 "\n",
288 fItemCount);
290 memberLocation = NULL;
293 return B_OK;
297 status_t
298 BListValueNode::CreateChildren(TeamTypeInformation* info)
300 return CreateChildrenInRange(info, 0, kMaxArrayElementCount);
304 int32
305 BListValueNode::CountChildren() const
307 return fChildren.CountItems();
311 ValueNodeChild*
312 BListValueNode::ChildAt(int32 index) const
314 return fChildren.ItemAt(index);
318 bool
319 BListValueNode::IsRangedContainer() const
321 return true;
325 bool
326 BListValueNode::IsContainerRangeFixed() const
328 return true;
332 void
333 BListValueNode::ClearChildren()
335 fChildren.MakeEmpty();
336 fCountChildCreated = false;
337 if (fContainer != NULL)
338 fContainer->NotifyValueNodeChildrenDeleted(this);
342 status_t
343 BListValueNode::CreateChildrenInRange(TeamTypeInformation* info,
344 int32 lowIndex, int32 highIndex)
346 if (fLocationResolutionState != B_OK)
347 return fLocationResolutionState;
349 if (lowIndex < 0)
350 lowIndex = 0;
351 if (highIndex >= fItemCount)
352 highIndex = fItemCount - 1;
354 if (!fCountChildCreated && fItemCountType != NULL) {
355 BListItemCountNodeChild* countChild = new(std::nothrow)
356 BListItemCountNodeChild(fItemCountLocation, this, fItemCountType);
358 if (countChild == NULL)
359 return B_NO_MEMORY;
361 fCountChildCreated = true;
362 countChild->SetContainer(fContainer);
363 fChildren.AddItem(countChild);
366 BReference<Type> addressTypeRef;
367 Type* type = NULL;
368 CompoundType* objectType = dynamic_cast<CompoundType*>(fType);
369 if (objectType->CountTemplateParameters() != 0) {
370 AddressType* addressType = NULL;
371 status_t result = objectType->TemplateParameterAt(0)->GetType()
372 ->CreateDerivedAddressType(DERIVED_TYPE_POINTER, addressType);
373 if (result != B_OK)
374 return result;
376 type = addressType;
377 addressTypeRef.SetTo(type, true);
378 } else {
379 BString typeName;
380 TypeLookupConstraints constraints;
381 constraints.SetTypeKind(TYPE_ADDRESS);
382 constraints.SetBaseTypeName("void");
383 status_t result = info->LookupTypeByName(typeName, constraints,
384 type);
385 if (result != B_OK)
386 return result;
389 for (int32 i = lowIndex; i <= highIndex; i++)
391 BListElementNodeChild* child =
392 new(std::nothrow) BListElementNodeChild(this, i, type);
393 if (child == NULL)
394 return B_NO_MEMORY;
395 child->SetContainer(fContainer);
396 fChildren.AddItem(child);
399 fChildrenCreated = true;
401 if (fContainer != NULL)
402 fContainer->NotifyValueNodeChildrenCreated(this);
404 return B_OK;
408 status_t
409 BListValueNode::SupportedChildRange(int32& lowIndex, int32& highIndex) const
411 lowIndex = 0;
412 highIndex = fItemCount - 1;
414 return B_OK;