vfs: check userland buffers before reading them.
[haiku.git] / src / kits / debugger / value / value_nodes / ArrayValueNode.cpp
blobf416145355ab4bd000ebb735d875fb35dc3e69bd
1 /*
2 * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
5 */
8 #include "ArrayValueNode.h"
10 #include <new>
12 #include "Architecture.h"
13 #include "ArrayIndexPath.h"
14 #include "IntegerValue.h"
15 #include "Tracing.h"
16 #include "Type.h"
17 #include "ValueLoader.h"
18 #include "ValueLocation.h"
19 #include "ValueNodeContainer.h"
22 // maximum number of array elements to show by default
23 static const uint64 kMaxArrayElementCount = 10;
26 // #pragma mark - AbstractArrayValueNode
29 AbstractArrayValueNode::AbstractArrayValueNode(ValueNodeChild* nodeChild,
30 ArrayType* type, int32 dimension)
32 ValueNode(nodeChild),
33 fType(type),
34 fDimension(dimension),
35 fLowerBound(0),
36 fUpperBound(0),
37 fBoundsInitialized(false)
39 fType->AcquireReference();
43 AbstractArrayValueNode::~AbstractArrayValueNode()
45 fType->ReleaseReference();
47 for (int32 i = 0; AbstractArrayValueNodeChild* child = fChildren.ItemAt(i);
48 i++) {
49 child->ReleaseReference();
54 Type*
55 AbstractArrayValueNode::GetType() const
57 return fType;
61 status_t
62 AbstractArrayValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
63 ValueLocation*& _location, Value*& _value)
65 // get the location
66 ValueLocation* location = NodeChild()->Location();
67 if (location == NULL)
68 return B_BAD_VALUE;
70 location->AcquireReference();
71 _location = location;
72 _value = NULL;
73 return B_OK;
77 status_t
78 AbstractArrayValueNode::CreateChildren(TeamTypeInformation* info)
80 if (!fChildren.IsEmpty())
81 return B_OK;
83 return CreateChildrenInRange(info, 0, kMaxArrayElementCount - 1);
87 int32
88 AbstractArrayValueNode::CountChildren() const
90 return fChildren.CountItems();
94 ValueNodeChild*
95 AbstractArrayValueNode::ChildAt(int32 index) const
97 return fChildren.ItemAt(index);
101 bool
102 AbstractArrayValueNode::IsRangedContainer() const
104 return true;
108 void
109 AbstractArrayValueNode::ClearChildren()
111 fChildren.MakeEmpty();
112 fLowerBound = 0;
113 fUpperBound = 0;
114 if (fContainer != NULL)
115 fContainer->NotifyValueNodeChildrenDeleted(this);
119 status_t
120 AbstractArrayValueNode::CreateChildrenInRange(TeamTypeInformation* info,
121 int32 lowIndex, int32 highIndex)
123 // TODO: ensure that we don't already have children in the specified
124 // index range. These need to be skipped if so.
125 TRACE_LOCALS("TYPE_ARRAY\n");
127 int32 dimensionCount = fType->CountDimensions();
128 bool isFinalDimension = fDimension + 1 == dimensionCount;
129 status_t error = B_OK;
131 if (!fBoundsInitialized) {
132 int32 lowerBound, upperBound;
133 error = SupportedChildRange(lowerBound, upperBound);
134 if (error != B_OK)
135 return error;
137 fLowerBound = lowerBound;
138 fUpperBound = upperBound;
139 fBoundsInitialized = true;
142 if (lowIndex < fLowerBound)
143 lowIndex = fLowerBound;
144 if (highIndex > fUpperBound)
145 highIndex = fUpperBound;
147 // create children for the array elements
148 for (int32 i = lowIndex; i <= highIndex; i++) {
149 BString name(Name());
150 name << '[' << i << ']';
151 if (name.Length() <= Name().Length())
152 return B_NO_MEMORY;
154 AbstractArrayValueNodeChild* child;
155 if (isFinalDimension) {
156 child = new(std::nothrow) ArrayValueNodeChild(this, name, i,
157 fType->BaseType());
158 } else {
159 child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i,
160 fType);
163 if (child == NULL || !fChildren.AddItem(child)) {
164 delete child;
165 return B_NO_MEMORY;
168 child->SetContainer(fContainer);
171 if (fContainer != NULL)
172 fContainer->NotifyValueNodeChildrenCreated(this);
174 return B_OK;
178 status_t
179 AbstractArrayValueNode::SupportedChildRange(int32& lowIndex,
180 int32& highIndex) const
182 if (!fBoundsInitialized) {
183 ArrayDimension* dimension = fType->DimensionAt(fDimension);
185 SubrangeType* dimensionType = dynamic_cast<SubrangeType*>(
186 dimension->GetType());
188 if (dimensionType != NULL) {
189 lowIndex = dimensionType->LowerBound().ToInt32();
190 highIndex = dimensionType->UpperBound().ToInt32();
191 } else
192 return B_UNSUPPORTED;
193 } else {
194 lowIndex = fLowerBound;
195 highIndex = fUpperBound;
198 return B_OK;
202 // #pragma mark - ArrayValueNode
205 ArrayValueNode::ArrayValueNode(ValueNodeChild* nodeChild, ArrayType* type)
207 AbstractArrayValueNode(nodeChild, type, 0)
212 ArrayValueNode::~ArrayValueNode()
217 // #pragma mark - InternalArrayValueNode
220 InternalArrayValueNode::InternalArrayValueNode(ValueNodeChild* nodeChild,
221 ArrayType* type, int32 dimension)
223 AbstractArrayValueNode(nodeChild, type, dimension)
228 InternalArrayValueNode::~InternalArrayValueNode()
233 // #pragma mark - AbstractArrayValueNodeChild
236 AbstractArrayValueNodeChild::AbstractArrayValueNodeChild(
237 AbstractArrayValueNode* parent, const BString& name, int64 elementIndex)
239 fParent(parent),
240 fName(name),
241 fElementIndex(elementIndex)
246 AbstractArrayValueNodeChild::~AbstractArrayValueNodeChild()
251 const BString&
252 AbstractArrayValueNodeChild::Name() const
254 return fName;
258 ValueNode*
259 AbstractArrayValueNodeChild::Parent() const
261 return fParent;
265 // #pragma mark - ArrayValueNodeChild
268 ArrayValueNodeChild::ArrayValueNodeChild(AbstractArrayValueNode* parent,
269 const BString& name, int64 elementIndex, Type* type)
271 AbstractArrayValueNodeChild(parent, name, elementIndex),
272 fType(type)
274 fType->AcquireReference();
278 ArrayValueNodeChild::~ArrayValueNodeChild()
280 fType->ReleaseReference();
284 Type*
285 ArrayValueNodeChild::GetType() const
287 return fType;
291 status_t
292 ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
293 ValueLocation*& _location)
295 // get the parent (== array) location
296 ValueLocation* parentLocation = fParent->Location();
297 if (parentLocation == NULL)
298 return B_BAD_VALUE;
300 // create an array index path
301 ArrayType* arrayType = fParent->GetArrayType();
302 int32 dimensionCount = arrayType->CountDimensions();
304 // add dummy indices first -- we'll replace them on our way back through
305 // our ancestors
306 ArrayIndexPath indexPath;
307 for (int32 i = 0; i < dimensionCount; i++) {
308 if (!indexPath.AddIndex(0))
309 return B_NO_MEMORY;
312 AbstractArrayValueNodeChild* child = this;
313 for (int32 i = dimensionCount - 1; i >= 0; i--) {
314 indexPath.SetIndexAt(i, child->ElementIndex());
316 child = dynamic_cast<AbstractArrayValueNodeChild*>(
317 child->ArrayParent()->NodeChild());
320 // resolve the element location
321 ValueLocation* location;
322 status_t error = arrayType->ResolveElementLocation(indexPath,
323 *parentLocation, location);
324 if (error != B_OK) {
325 TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): "
326 "ResolveElementLocation() failed: %s\n", strerror(error));
327 return error;
330 _location = location;
331 return B_OK;
335 // #pragma mark - InternalArrayValueNodeChild
338 InternalArrayValueNodeChild::InternalArrayValueNodeChild(
339 AbstractArrayValueNode* parent, const BString& name, int64 elementIndex,
340 ArrayType* type)
342 AbstractArrayValueNodeChild(parent, name, elementIndex),
343 fType(type)
345 fType->AcquireReference();
349 InternalArrayValueNodeChild::~InternalArrayValueNodeChild()
351 fType->ReleaseReference();
355 Type*
356 InternalArrayValueNodeChild::GetType() const
358 return fType;
362 bool
363 InternalArrayValueNodeChild::IsInternal() const
365 return true;
369 status_t
370 InternalArrayValueNodeChild::CreateInternalNode(ValueNode*& _node)
372 ValueNode* node = new(std::nothrow) InternalArrayValueNode(this, fType,
373 fParent->Dimension() + 1);
374 if (node == NULL)
375 return B_NO_MEMORY;
377 _node = node;
378 return B_OK;
382 status_t
383 InternalArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
384 ValueLocation*& _location)
386 // This is an internal child node for a non-final dimension -- just clone
387 // the parent's location.
388 ValueLocation* parentLocation = fParent->Location();
389 if (parentLocation == NULL)
390 return B_BAD_VALUE;
392 parentLocation->AcquireReference();
393 _location = parentLocation;
395 return B_OK;