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