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