1/*
2 * Copyright 2010, Rene Gollent, rene@gollent.com
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "CStringValueNode.h"
8
9#include <new>
10
11#include "Architecture.h"
12#include "StringValue.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 - CStringValueNode
21
22
23CStringValueNode::CStringValueNode(ValueNodeChild* nodeChild,
24	Type* type)
25	:
26	ChildlessValueNode(nodeChild),
27	fType(type)
28{
29	fType->AcquireReference();
30}
31
32
33CStringValueNode::~CStringValueNode()
34{
35	fType->ReleaseReference();
36}
37
38
39Type*
40CStringValueNode::GetType() const
41{
42	return fType;
43}
44
45
46status_t
47CStringValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
48	ValueLocation*& _location, Value*& _value)
49{
50	// get the location
51	ValueLocation* location = NodeChild()->Location();
52	if (location == NULL)
53		return B_BAD_VALUE;
54
55	TRACE_LOCALS("  TYPE_ADDRESS (C string)\n");
56
57	// get the value type
58	type_code valueType;
59	if (valueLoader->GetArchitecture()->AddressSize() == 4) {
60		valueType = B_UINT32_TYPE;
61		TRACE_LOCALS("    -> 32 bit\n");
62	} else {
63		valueType = B_UINT64_TYPE;
64		TRACE_LOCALS("    -> 64 bit\n");
65	}
66
67	// load the value data
68
69	BVariant addressData;
70	BString valueData;
71	status_t error = B_OK;
72	size_t maxSize = 255;
73	if (dynamic_cast<AddressType*>(fType) != NULL) {
74		error = valueLoader->LoadValue(location, valueType, false,
75			addressData);
76		if (error != B_OK)
77			return error;
78	} else {
79		addressData.SetTo(location->PieceAt(0).address);
80		maxSize = dynamic_cast<ArrayType*>(fType)
81			->DimensionAt(0)->CountElements();
82	}
83
84	ValuePieceLocation piece;
85	piece.SetToMemory(addressData.ToUInt64());
86
87	TRACE_LOCALS("    Address found: %#" B_PRIx64 "\n",
88		addressData.ToUInt64());
89
90	error = valueLoader->LoadStringValue(addressData, maxSize, valueData);
91	if (error != B_OK)
92		return error;
93
94	piece.size = valueData.Length();
95
96	TRACE_LOCALS("    String value found, length: %" B_PRIu64 "bytes\n",
97		piece.size);
98
99	ValueLocation* stringLocation = new(std::nothrow) ValueLocation(
100		valueLoader->GetArchitecture()->IsBigEndian(), piece);
101
102	if (stringLocation == NULL)
103		return B_NO_MEMORY;
104
105	BReference<ValueLocation> locationReference(stringLocation, true);
106
107	error = valueLoader->LoadStringValue(addressData, maxSize, valueData);
108	if (error != B_OK)
109		return error;
110
111	// create the type object
112	Value* value = new(std::nothrow) StringValue(valueData);
113	if (value == NULL)
114		return B_NO_MEMORY;
115
116	NodeChild()->SetLocation(stringLocation, B_OK);
117	_location = locationReference.Detach();
118	_value = value;
119	return B_OK;
120}
121