| //------------------------------------------------------------------------------------------------------- |
| // 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 TValue> |
| 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<TValue>&) |
| { |
| return false; |
| } |
| |
| TValue const& Value() const { return value; } |
| TValue& Value() { return value; } |
| void SetValue(TValue const& value) { this->value = value; } |
| }; |
| |
| template <class TValue> |
| class ValueEntry: public BaseValueEntry<TValue> |
| { |
| public: |
| void Clear() |
| { |
| } |
| }; |
| |
| // Class specialization for pointer values to support clearing |
| template <class TValue> |
| class ValueEntry<TValue*>: public BaseValueEntry<TValue*> |
| { |
| public: |
| void Clear() |
| { |
| this->value = nullptr; |
| } |
| }; |
| |
| template <> |
| class ValueEntry<bool>: public BaseValueEntry<bool> |
| { |
| public: |
| void Clear() |
| { |
| this->value = false; |
| } |
| }; |
| |
| template <> |
| class ValueEntry<int>: public BaseValueEntry<int> |
| { |
| public: |
| void Clear() |
| { |
| this->value = 0; |
| } |
| }; |
| |
| template <> |
| class ValueEntry<uint>: public BaseValueEntry<uint> |
| { |
| public: |
| void Clear() |
| { |
| this->value = 0; |
| } |
| }; |
| |
| template<class TKey, class TValue> |
| struct ValueToKey |
| { |
| static TKey ToKey(const TValue &value) { return static_cast<TKey>(value); } |
| }; |
| |
| // Used by BaseHashSet, the default is that the key is the same as the value |
| template <class TKey, class TValue> |
| class ImplicitKeyValueEntry : public ValueEntry<TValue> |
| { |
| public: |
| inline TKey Key() const { return ValueToKey<TKey, TValue>::ToKey(this->value); } |
| |
| void Set(TKey const& key, TValue const& value) |
| { |
| __super::Set(value); |
| } |
| }; |
| |
| template <class TKey, class TValue> |
| class BaseKeyValueEntry : public ValueEntry<TValue> |
| { |
| 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 TKey, class TValue> |
| class KeyValueEntry : public BaseKeyValueEntry<TKey, TValue> |
| { |
| }; |
| |
| template <class TKey, class TValue> |
| class KeyValueEntry<TKey*, TValue> : public BaseKeyValueEntry<TKey*, TValue> |
| { |
| public: |
| void Clear() |
| { |
| __super::Clear(); |
| this->key = nullptr; |
| } |
| }; |
| |
| template <class TValue> |
| class KeyValueEntry<int, TValue> : public BaseKeyValueEntry<int, TValue> |
| { |
| public: |
| void Clear() |
| { |
| __super::Clear(); |
| this->key = 0; |
| } |
| }; |
| |
| template <class TKey, class TValue, template <class K, class V> class THashEntry> |
| class DefaultHashedEntry : public THashEntry<TKey, TValue> |
| { |
| public: |
| template<typename Comparer, typename TLookup> |
| inline bool KeyEquals(TLookup const& otherKey, hash_t otherHashCode) |
| { |
| return Comparer::Equals(this->Key(), otherKey); |
| } |
| |
| template<typename Comparer> |
| 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 TKey, class TValue, template <class K, class V> class THashEntry> |
| class CacheHashedEntry : public THashEntry<TKey, TValue> |
| { |
| hash_t hashCode; // Lower 31 bits of hash code << 1 | 1, 0 if unused |
| public: |
| static const int INVALID_HASH_VALUE = 0; |
| template<typename Comparer, typename TLookup> |
| 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<typename Comparer> |
| 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 TKey, class TValue> |
| class SimpleHashedEntry : public DefaultHashedEntry<TKey, TValue, ImplicitKeyValueEntry> {}; |
| |
| template <class TKey, class TValue> |
| class HashedEntry : public CacheHashedEntry<TKey, TValue, ImplicitKeyValueEntry> {}; |
| |
| template <class TKey, class TValue> |
| class SimpleDictionaryEntry : public DefaultHashedEntry<TKey, TValue, KeyValueEntry> {}; |
| |
| template <class TKey, class TValue> |
| class DictionaryEntry: public CacheHashedEntry<TKey, TValue, KeyValueEntry> {}; |
| |
| template <class TKey, class TValue> |
| class WeakRefValueDictionaryEntry: public SimpleDictionaryEntry<TKey, TValue> |
| { |
| public: |
| void Clear() |
| { |
| this->key = TKey(); |
| this->value = TValue(); |
| } |
| |
| static bool SupportsCleanup() |
| { |
| return true; |
| } |
| |
| static bool NeedsCleanup(WeakRefValueDictionaryEntry<TKey, TValue> const& entry) |
| { |
| TValue weakReference = entry.Value(); |
| |
| return (weakReference == nullptr || weakReference->Get() == nullptr); |
| } |
| }; |
| } |