/* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include "StackFrameValues.h" #include #include "FunctionID.h" #include "TypeComponentPath.h" struct StackFrameValues::Key { ObjectID* variable; TypeComponentPath* path; Key(ObjectID* variable, TypeComponentPath* path) : variable(variable), path(path) { } uint32 HashValue() const { return variable->HashValue() ^ path->HashValue(); } bool operator==(const Key& other) const { return *variable == *other.variable && *path == *other.path; } }; struct StackFrameValues::ValueEntry : Key { BVariant value; ValueEntry* next; ValueEntry(ObjectID* variable, TypeComponentPath* path) : Key(variable, path) { variable->AcquireReference(); path->AcquireReference(); } ~ValueEntry() { variable->ReleaseReference(); path->ReleaseReference(); } }; struct StackFrameValues::ValueEntryHashDefinition { typedef Key KeyType; typedef ValueEntry ValueType; size_t HashKey(const Key& key) const { return key.HashValue(); } size_t Hash(const ValueEntry* value) const { return value->HashValue(); } bool Compare(const Key& key, const ValueEntry* value) const { return key == *value; } ValueEntry*& GetLink(ValueEntry* value) const { return value->next; } }; StackFrameValues::StackFrameValues() : fValues(NULL) { } StackFrameValues::StackFrameValues(const StackFrameValues& other) : fValues(NULL) { try { // init if (Init() != B_OK) throw std::bad_alloc(); // clone all values for (ValueTable::Iterator it = other.fValues->GetIterator(); ValueEntry* entry = it.Next();) { if (SetValue(entry->variable, entry->path, entry->value) != B_OK) throw std::bad_alloc(); } } catch (...) { _Cleanup(); throw; } } StackFrameValues::~StackFrameValues() { _Cleanup(); } status_t StackFrameValues::Init() { fValues = new(std::nothrow) ValueTable; if (fValues == NULL) return B_NO_MEMORY; return fValues->Init(); } bool StackFrameValues::GetValue(ObjectID* variable, const TypeComponentPath* path, BVariant& _value) const { ValueEntry* entry = fValues->Lookup( Key(variable, (TypeComponentPath*)path)); if (entry == NULL) return false; _value = entry->value; return true; } bool StackFrameValues::HasValue(ObjectID* variable, const TypeComponentPath* path) const { return fValues->Lookup(Key(variable, (TypeComponentPath*)path)) != NULL; } status_t StackFrameValues::SetValue(ObjectID* variable, TypeComponentPath* path, const BVariant& value) { ValueEntry* entry = fValues->Lookup(Key(variable, path)); if (entry == NULL) { entry = new(std::nothrow) ValueEntry(variable, path); if (entry == NULL) return B_NO_MEMORY; fValues->Insert(entry); } entry->value = value; return B_OK; } void StackFrameValues::_Cleanup() { if (fValues != NULL) { ValueEntry* entry = fValues->Clear(true); while (entry != NULL) { ValueEntry* next = entry->next; delete entry; entry = next; } delete fValues; fValues = NULL; } }