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