xref: /haiku/src/kits/debugger/model/ExpressionValues.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 
17 struct 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 
45 struct 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 
66 struct 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 
92 ExpressionValues::ExpressionValues()
93 	:
94 	fValues(NULL)
95 {
96 }
97 
98 
99 ExpressionValues::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 
123 ExpressionValues::~ExpressionValues()
124 {
125 	_Cleanup();
126 }
127 
128 
129 status_t
130 ExpressionValues::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 
140 bool
141 ExpressionValues::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 
153 bool
154 ExpressionValues::HasValue(FunctionID* function, ::Thread* thread,
155 	const BString* expression) const
156 {
157 	return fValues->Lookup(Key(function, thread, *expression)) != NULL;
158 }
159 
160 
161 status_t
162 ExpressionValues::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 
178 void
179 ExpressionValues::_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