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