//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once namespace JsUtil { template class BaseValueEntry { protected: TValue value; // data of entry void Set(TValue const& value) { this->value = value; } public: int next; // Index of next entry, -1 if last static bool SupportsCleanup() { return false; } static bool NeedsCleanup(BaseValueEntry&) { return false; } TValue const& Value() const { return value; } TValue& Value() { return value; } void SetValue(TValue const& value) { this->value = value; } }; template class ValueEntry: public BaseValueEntry { public: void Clear() { } }; // Class specialization for pointer values to support clearing template class ValueEntry: public BaseValueEntry { public: void Clear() { this->value = nullptr; } }; template <> class ValueEntry: public BaseValueEntry { public: void Clear() { this->value = false; } }; template <> class ValueEntry: public BaseValueEntry { public: void Clear() { this->value = 0; } }; template <> class ValueEntry: public BaseValueEntry { public: void Clear() { this->value = 0; } }; template struct ValueToKey { static TKey ToKey(const TValue &value) { return static_cast(value); } }; // Used by BaseHashSet, the default is that the key is the same as the value template class ImplicitKeyValueEntry : public ValueEntry { public: inline TKey Key() const { return ValueToKey::ToKey(this->value); } void Set(TKey const& key, TValue const& value) { __super::Set(value); } }; template class BaseKeyValueEntry : public ValueEntry { protected: TKey key; // key of entry void Set(TKey const& key, TValue const& value) { __super::Set(value); this->key = key; } public: TKey const& Key() const { return key; } }; template class KeyValueEntry : public BaseKeyValueEntry { }; template class KeyValueEntry : public BaseKeyValueEntry { public: void Clear() { __super::Clear(); this->key = nullptr; } }; template class KeyValueEntry : public BaseKeyValueEntry { public: void Clear() { __super::Clear(); this->key = 0; } }; template class THashEntry> class DefaultHashedEntry : public THashEntry { public: template inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode) { return Comparer::Equals(this->Key(), otherKey); } template inline hash_t GetHashCode() { return ((Comparer::GetHashCode(this->Key()) & 0x7fffffff) << 1) | 1; } void Set(TKey const& key, TValue const& value, int hashCode) { __super::Set(key, value); } }; template class THashEntry> class CacheHashedEntry : public THashEntry { hash_t hashCode; // Lower 31 bits of hash code << 1 | 1, 0 if unused public: static const int INVALID_HASH_VALUE = 0; template inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode) { Assert(TAGHASH(Comparer::GetHashCode(this->Key())) == this->hashCode); return this->hashCode == otherHashCode && Comparer::Equals(this->Key(), otherKey); } template inline hash_t GetHashCode() { Assert(TAGHASH(Comparer::GetHashCode(this->Key())) == this->hashCode); return hashCode; } void Set(TKey const& key, TValue const& value, hash_t hashCode) { __super::Set(key, value); this->hashCode = hashCode; } void Clear() { __super::Clear(); this->hashCode = INVALID_HASH_VALUE; } }; template class SimpleHashedEntry : public DefaultHashedEntry {}; template class HashedEntry : public CacheHashedEntry {}; template class SimpleDictionaryEntry : public DefaultHashedEntry {}; template class DictionaryEntry: public CacheHashedEntry {}; template class WeakRefValueDictionaryEntry: public SimpleDictionaryEntry { public: void Clear() { this->key = TKey(); this->value = TValue(); } static bool SupportsCleanup() { return true; } static bool NeedsCleanup(WeakRefValueDictionaryEntry const& entry) { TValue weakReference = entry.Value(); return (weakReference == nullptr || weakReference->Get() == nullptr); } }; }