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