1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "StackFrameValues.h"
8
9#include <new>
10
11#include "FunctionID.h"
12#include "TypeComponentPath.h"
13
14
15struct StackFrameValues::Key {
16	ObjectID*			variable;
17	TypeComponentPath*	path;
18
19	Key(ObjectID* variable, TypeComponentPath* path)
20		:
21		variable(variable),
22		path(path)
23	{
24	}
25
26	uint32 HashValue() const
27	{
28		return variable->HashValue() ^ path->HashValue();
29	}
30
31	bool operator==(const Key& other) const
32	{
33		return *variable == *other.variable && *path == *other.path;
34	}
35};
36
37
38struct StackFrameValues::ValueEntry : Key {
39	BVariant			value;
40	ValueEntry*			next;
41
42	ValueEntry(ObjectID* variable, TypeComponentPath* path)
43		:
44		Key(variable, path)
45	{
46		variable->AcquireReference();
47		path->AcquireReference();
48	}
49
50	~ValueEntry()
51	{
52		variable->ReleaseReference();
53		path->ReleaseReference();
54	}
55};
56
57
58struct StackFrameValues::ValueEntryHashDefinition {
59	typedef Key			KeyType;
60	typedef	ValueEntry	ValueType;
61
62	size_t HashKey(const Key& key) const
63	{
64		return key.HashValue();
65	}
66
67	size_t Hash(const ValueEntry* value) const
68	{
69		return value->HashValue();
70	}
71
72	bool Compare(const Key& key, const ValueEntry* value) const
73	{
74		return key == *value;
75	}
76
77	ValueEntry*& GetLink(ValueEntry* value) const
78	{
79		return value->next;
80	}
81};
82
83
84StackFrameValues::StackFrameValues()
85	:
86	fValues(NULL)
87{
88}
89
90
91StackFrameValues::StackFrameValues(const StackFrameValues& other)
92	:
93	fValues(NULL)
94{
95	try {
96		// init
97		if (Init() != B_OK)
98			throw std::bad_alloc();
99
100		// clone all values
101		for (ValueTable::Iterator it = other.fValues->GetIterator();
102				ValueEntry* entry = it.Next();) {
103			if (SetValue(entry->variable, entry->path, entry->value) != B_OK)
104				throw std::bad_alloc();
105		}
106	} catch (...) {
107		_Cleanup();
108		throw;
109	}
110}
111
112
113StackFrameValues::~StackFrameValues()
114{
115	_Cleanup();
116}
117
118
119status_t
120StackFrameValues::Init()
121{
122	fValues = new(std::nothrow) ValueTable;
123	if (fValues == NULL)
124		return B_NO_MEMORY;
125
126	return fValues->Init();
127}
128
129
130bool
131StackFrameValues::GetValue(ObjectID* variable, const TypeComponentPath* path,
132	BVariant& _value) const
133{
134	ValueEntry* entry = fValues->Lookup(
135		Key(variable, (TypeComponentPath*)path));
136	if (entry == NULL)
137		return false;
138
139	_value = entry->value;
140	return true;
141}
142
143
144bool
145StackFrameValues::HasValue(ObjectID* variable, const TypeComponentPath* path)
146	const
147{
148	return fValues->Lookup(Key(variable, (TypeComponentPath*)path)) != NULL;
149}
150
151
152status_t
153StackFrameValues::SetValue(ObjectID* variable, TypeComponentPath* path,
154	const BVariant& value)
155{
156	ValueEntry* entry = fValues->Lookup(Key(variable, path));
157	if (entry == NULL) {
158		entry = new(std::nothrow) ValueEntry(variable, path);
159		if (entry == NULL)
160			return B_NO_MEMORY;
161		fValues->Insert(entry);
162	}
163
164	entry->value = value;
165	return B_OK;
166}
167
168
169void
170StackFrameValues::_Cleanup()
171{
172	if (fValues != NULL) {
173		ValueEntry* entry = fValues->Clear(true);
174
175		while (entry != NULL) {
176			ValueEntry* next = entry->next;
177			delete entry;
178			entry = next;
179		}
180
181		delete fValues;
182		fValues = NULL;
183	}
184}
185