xref: /haiku/src/kits/debugger/value/value_nodes/CompoundValueNode.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 
24 class CompoundValueNode::Child : public ValueNodeChild {
25 public:
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 
43 protected:
44 	CompoundValueNode*	fParent;
45 	BString				fName;
46 };
47 
48 
49 // #pragma mark - BaseTypeChild
50 
51 
52 class CompoundValueNode::BaseTypeChild : public Child {
53 public:
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 
94 private:
95 	BaseType*	fBaseType;
96 };
97 
98 
99 // #pragma mark - MemberChild
100 
101 
102 class CompoundValueNode::MemberChild : public Child {
103 public:
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 
144 private:
145 	DataMember*	fMember;
146 };
147 
148 
149 // #pragma mark - CompoundValueNode
150 
151 
152 CompoundValueNode::CompoundValueNode(ValueNodeChild* nodeChild,
153 	CompoundType* type)
154 	:
155 	ValueNode(nodeChild),
156 	fType(type)
157 {
158 	fType->AcquireReference();
159 }
160 
161 
162 CompoundValueNode::~CompoundValueNode()
163 {
164 	fType->ReleaseReference();
165 
166 	for (int32 i = 0; Child* child = fChildren.ItemAt(i); i++)
167 		child->ReleaseReference();
168 }
169 
170 
171 Type*
172 CompoundValueNode::GetType() const
173 {
174 	return fType;
175 }
176 
177 
178 status_t
179 CompoundValueNode::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 
194 status_t
195 CompoundValueNode::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 
233 int32
234 CompoundValueNode::CountChildren() const
235 {
236 	return fChildren.CountItems();
237 }
238 
239 
240 ValueNodeChild*
241 CompoundValueNode::ChildAt(int32 index) const
242 {
243 	return fChildren.ItemAt(index);
244 }
245