xref: /haiku/src/kits/debugger/value/value_nodes/BListValueNode.cpp (revision ffe684b96c6425bfc5489c74e59df990d4b739c7)
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