1/*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "CompoundValueNode.h"
8
9#include <new>
10
11#include "Architecture.h"
12#include "IntegerValue.h"
13#include "Tracing.h"
14#include "Type.h"
15#include "ValueLoader.h"
16#include "ValueLocation.h"
17#include "ValueNodeContainer.h"
18
19
20// #pragma mark - Child
21
22
23class CompoundValueNode::Child : public ValueNodeChild {
24public:
25	Child(CompoundValueNode* parent, const BString& name)
26		:
27		fParent(parent),
28		fName(name)
29	{
30	}
31
32	virtual const BString& Name() const
33	{
34		return fName;
35	}
36
37	virtual ValueNode* Parent() const
38	{
39		return fParent;
40	}
41
42protected:
43	CompoundValueNode*	fParent;
44	BString				fName;
45};
46
47
48// #pragma mark - BaseTypeChild
49
50
51class CompoundValueNode::BaseTypeChild : public Child {
52public:
53	BaseTypeChild(CompoundValueNode* parent, BaseType* baseType)
54		:
55		Child(parent, baseType->GetType()->Name()),
56		fBaseType(baseType)
57	{
58		fBaseType->AcquireReference();
59	}
60
61	virtual ~BaseTypeChild()
62	{
63		fBaseType->ReleaseReference();
64	}
65
66	virtual Type* GetType() const
67	{
68		return fBaseType->GetType();
69	}
70
71	virtual status_t ResolveLocation(ValueLoader* valueLoader,
72		ValueLocation*& _location)
73	{
74		// The parent's location refers to the location of the complete
75		// object. We want to extract the location of a member.
76		ValueLocation* parentLocation = fParent->Location();
77		if (parentLocation == NULL)
78			return B_BAD_VALUE;
79
80		ValueLocation* location;
81		status_t error = fParent->fType->ResolveBaseTypeLocation(fBaseType,
82			*parentLocation, location);
83		if (error != B_OK) {
84			TRACE_LOCALS("CompoundValueNode::BaseTypeChild::ResolveLocation(): "
85				"ResolveBaseTypeLocation() failed: %s\n", strerror(error));
86			return error;
87		}
88
89		_location = location;
90		return B_OK;
91	}
92
93private:
94	BaseType*	fBaseType;
95};
96
97
98// #pragma mark - MemberChild
99
100
101class CompoundValueNode::MemberChild : public Child {
102public:
103	MemberChild(CompoundValueNode* parent, DataMember* member)
104		:
105		Child(parent, member->Name()),
106		fMember(member)
107	{
108		fMember->AcquireReference();
109	}
110
111	virtual ~MemberChild()
112	{
113		fMember->ReleaseReference();
114	}
115
116	virtual Type* GetType() const
117	{
118		return fMember->GetType();
119	}
120
121	virtual status_t ResolveLocation(ValueLoader* valueLoader,
122		ValueLocation*& _location)
123	{
124		// The parent's location refers to the location of the complete
125		// object. We want to extract the location of a member.
126		ValueLocation* parentLocation = fParent->Location();
127		if (parentLocation == NULL)
128			return B_BAD_VALUE;
129
130		ValueLocation* location;
131		status_t error = fParent->fType->ResolveDataMemberLocation(fMember,
132			*parentLocation, location);
133		if (error != B_OK) {
134			TRACE_LOCALS("CompoundValueNode::MemberChild::ResolveLocation(): "
135				"ResolveDataMemberLocation() failed: %s\n", strerror(error));
136			return error;
137		}
138
139		_location = location;
140		return B_OK;
141	}
142
143private:
144	DataMember*	fMember;
145};
146
147
148// #pragma mark - CompoundValueNode
149
150
151CompoundValueNode::CompoundValueNode(ValueNodeChild* nodeChild,
152	CompoundType* type)
153	:
154	ValueNode(nodeChild),
155	fType(type)
156{
157	fType->AcquireReference();
158}
159
160
161CompoundValueNode::~CompoundValueNode()
162{
163	fType->ReleaseReference();
164
165	for (int32 i = 0; Child* child = fChildren.ItemAt(i); i++)
166		child->ReleaseReference();
167}
168
169
170Type*
171CompoundValueNode::GetType() const
172{
173	return fType;
174}
175
176
177status_t
178CompoundValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
179	ValueLocation*& _location, Value*& _value)
180{
181	// get the location
182	ValueLocation* location = NodeChild()->Location();
183	if (location == NULL)
184		return B_BAD_VALUE;
185
186	location->AcquireReference();
187	_location = location;
188	_value = NULL;
189	return B_OK;
190}
191
192
193status_t
194CompoundValueNode::CreateChildren()
195{
196	if (!fChildren.IsEmpty())
197		return B_OK;
198
199	// base types
200	for (int32 i = 0; BaseType* baseType = fType->BaseTypeAt(i); i++) {
201		TRACE_LOCALS("  base %" B_PRId32 "\n", i);
202
203		BaseTypeChild* child = new(std::nothrow) BaseTypeChild(this, baseType);
204		if (child == NULL || !fChildren.AddItem(child)) {
205			delete child;
206			return B_NO_MEMORY;
207		}
208
209		child->SetContainer(fContainer);
210	}
211
212	// members
213	for (int32 i = 0; DataMember* member = fType->DataMemberAt(i); i++) {
214		TRACE_LOCALS("  member %" B_PRId32 ": \"%s\"\n", i, member->Name());
215
216		MemberChild* child = new(std::nothrow) MemberChild(this, member);
217		if (child == NULL || !fChildren.AddItem(child)) {
218			delete child;
219			return B_NO_MEMORY;
220		}
221
222		child->SetContainer(fContainer);
223	}
224
225	if (fContainer != NULL)
226		fContainer->NotifyValueNodeChildrenCreated(this);
227
228	return B_OK;
229}
230
231
232int32
233CompoundValueNode::CountChildren() const
234{
235	return fChildren.CountItems();
236}
237
238
239ValueNodeChild*
240CompoundValueNode::ChildAt(int32 index) const
241{
242	return fChildren.ItemAt(index);
243}
244