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