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.
8 #include "ArrayValueNode.h"
12 #include "Architecture.h"
13 #include "ArrayIndexPath.h"
14 #include "IntegerValue.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
)
34 fDimension(dimension
),
37 fBoundsInitialized(false)
39 fType
->AcquireReference();
43 AbstractArrayValueNode::~AbstractArrayValueNode()
45 fType
->ReleaseReference();
47 for (int32 i
= 0; AbstractArrayValueNodeChild
* child
= fChildren
.ItemAt(i
);
49 child
->ReleaseReference();
55 AbstractArrayValueNode::GetType() const
62 AbstractArrayValueNode::ResolvedLocationAndValue(ValueLoader
* valueLoader
,
63 ValueLocation
*& _location
, Value
*& _value
)
66 ValueLocation
* location
= NodeChild()->Location();
70 location
->AcquireReference();
78 AbstractArrayValueNode::CreateChildren(TeamTypeInformation
* info
)
80 if (!fChildren
.IsEmpty())
83 return CreateChildrenInRange(info
, 0, kMaxArrayElementCount
- 1);
88 AbstractArrayValueNode::CountChildren() const
90 return fChildren
.CountItems();
95 AbstractArrayValueNode::ChildAt(int32 index
) const
97 return fChildren
.ItemAt(index
);
102 AbstractArrayValueNode::IsRangedContainer() const
109 AbstractArrayValueNode::ClearChildren()
111 fChildren
.MakeEmpty();
114 if (fContainer
!= NULL
)
115 fContainer
->NotifyValueNodeChildrenDeleted(this);
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
);
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())
154 AbstractArrayValueNodeChild
* child
;
155 if (isFinalDimension
) {
156 child
= new(std::nothrow
) ArrayValueNodeChild(this, name
, i
,
159 child
= new(std::nothrow
) InternalArrayValueNodeChild(this, name
, i
,
163 if (child
== NULL
|| !fChildren
.AddItem(child
)) {
168 child
->SetContainer(fContainer
);
171 if (fContainer
!= NULL
)
172 fContainer
->NotifyValueNodeChildrenCreated(this);
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();
192 return B_UNSUPPORTED
;
194 lowIndex
= fLowerBound
;
195 highIndex
= fUpperBound
;
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
)
241 fElementIndex(elementIndex
)
246 AbstractArrayValueNodeChild::~AbstractArrayValueNodeChild()
252 AbstractArrayValueNodeChild::Name() const
259 AbstractArrayValueNodeChild::Parent() const
265 // #pragma mark - ArrayValueNodeChild
268 ArrayValueNodeChild::ArrayValueNodeChild(AbstractArrayValueNode
* parent
,
269 const BString
& name
, int64 elementIndex
, Type
* type
)
271 AbstractArrayValueNodeChild(parent
, name
, elementIndex
),
274 fType
->AcquireReference();
278 ArrayValueNodeChild::~ArrayValueNodeChild()
280 fType
->ReleaseReference();
285 ArrayValueNodeChild::GetType() const
292 ArrayValueNodeChild::ResolveLocation(ValueLoader
* valueLoader
,
293 ValueLocation
*& _location
)
295 // get the parent (== array) location
296 ValueLocation
* parentLocation
= fParent
->Location();
297 if (parentLocation
== NULL
)
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
306 ArrayIndexPath indexPath
;
307 for (int32 i
= 0; i
< dimensionCount
; i
++) {
308 if (!indexPath
.AddIndex(0))
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
);
325 TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): "
326 "ResolveElementLocation() failed: %s\n", strerror(error
));
330 _location
= location
;
335 // #pragma mark - InternalArrayValueNodeChild
338 InternalArrayValueNodeChild::InternalArrayValueNodeChild(
339 AbstractArrayValueNode
* parent
, const BString
& name
, int64 elementIndex
,
342 AbstractArrayValueNodeChild(parent
, name
, elementIndex
),
345 fType
->AcquireReference();
349 InternalArrayValueNodeChild::~InternalArrayValueNodeChild()
351 fType
->ReleaseReference();
356 InternalArrayValueNodeChild::GetType() const
363 InternalArrayValueNodeChild::IsInternal() const
370 InternalArrayValueNodeChild::CreateInternalNode(ValueNode
*& _node
)
372 ValueNode
* node
= new(std::nothrow
) InternalArrayValueNode(this, fType
,
373 fParent
->Dimension() + 1);
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
)
392 parentLocation
->AcquireReference();
393 _location
= parentLocation
;