summaryrefslogtreecommitdiff
path: root/source/core/slang-dictionary.h
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2024-10-29 14:49:26 +0800
committerGitHub <noreply@github.com>2024-10-29 14:49:26 +0800
commitf65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch)
treeea1d61342cd29368e19135000ec2948813096205 /source/core/slang-dictionary.h
parenta729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff)
format
* format * Minor test fixes * enable checking cpp format in ci
Diffstat (limited to 'source/core/slang-dictionary.h')
-rw-r--r--source/core/slang-dictionary.h1306
1 files changed, 636 insertions, 670 deletions
diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h
index 9c753ffcd..79f6dee30 100644
--- a/source/core/slang-dictionary.h
+++ b/source/core/slang-dictionary.h
@@ -1,786 +1,752 @@
#ifndef SLANG_CORE_DICTIONARY_H
#define SLANG_CORE_DICTIONARY_H
-#include "slang-list.h"
-#include "slang-linked-list.h"
+#include "../../external/unordered_dense/include/ankerl/unordered_dense.h"
#include "slang-common.h"
-#include "slang-uint-set.h"
#include "slang-exception.h"
-#include "slang-math.h"
#include "slang-hash.h"
-
-#include "../../external/unordered_dense/include/ankerl/unordered_dense.h"
+#include "slang-linked-list.h"
+#include "slang-list.h"
+#include "slang-math.h"
+#include "slang-uint-set.h"
#include <initializer_list>
namespace Slang
{
- template<typename TKey, typename TValue>
- class KeyValuePair
+template<typename TKey, typename TValue>
+class KeyValuePair
+{
+public:
+ TKey key;
+ TValue value;
+ KeyValuePair() {}
+ KeyValuePair(const TKey& inKey, const TValue& inValue)
{
- public:
- TKey key;
- TValue value;
- KeyValuePair()
- {}
- KeyValuePair(const TKey& inKey, const TValue& inValue)
- {
- key = inKey;
- value = inValue;
- }
- KeyValuePair(TKey&& inKey, TValue&& inValue)
- {
- key = _Move(inKey);
- value = _Move(inValue);
- }
- KeyValuePair(TKey&& inKey, const TValue& inValue)
- {
- key = _Move(inKey);
- value = inValue;
- }
- KeyValuePair(const KeyValuePair<TKey, TValue>& that)
- {
- key = that.key;
- value = that.value;
- }
- KeyValuePair(KeyValuePair<TKey, TValue>&& that)
- {
- operator=(_Move(that));
- }
- KeyValuePair& operator=(KeyValuePair<TKey, TValue>&& that)
- {
- key = _Move(that.key);
- value = _Move(that.value);
- return *this;
- }
- KeyValuePair& operator=(const KeyValuePair<TKey, TValue>& that)
- {
- key = that.key;
- value = that.value;
- return *this;
- }
- HashCode getHashCode() const
- {
- return combineHash(
- Slang::getHashCode(key),
- Slang::getHashCode(value));
- }
- bool operator==(const KeyValuePair<TKey, TValue>& that) const
- {
- return (key == that.key) && (value == that.value);
- }
- };
-
- template<typename TKey, typename TValue>
- inline KeyValuePair<TKey, TValue> KVPair(const TKey& k, const TValue& v)
+ key = inKey;
+ value = inValue;
+ }
+ KeyValuePair(TKey&& inKey, TValue&& inValue)
{
- return KeyValuePair<TKey, TValue>(k, v);
+ key = _Move(inKey);
+ value = _Move(inValue);
}
-
- namespace KeyValueDetail {
-
- template <typename KEY, typename VALUE>
- SLANG_FORCE_INLINE const KEY* getKey(const std::pair<KEY, VALUE>* in)
+ KeyValuePair(TKey&& inKey, const TValue& inValue)
{
- return &in->first;
+ key = _Move(inKey);
+ value = inValue;
}
- template <typename KEY, typename VALUE>
- SLANG_FORCE_INLINE const KEY* getKey(const KeyValuePair<KEY, VALUE>* in)
+ KeyValuePair(const KeyValuePair<TKey, TValue>& that)
{
- return &in->key;
+ key = that.key;
+ value = that.value;
}
-
- template <typename KEY, typename VALUE>
- SLANG_FORCE_INLINE const VALUE* getValue(const std::pair<KEY, VALUE>* in)
+ KeyValuePair(KeyValuePair<TKey, TValue>&& that) { operator=(_Move(that)); }
+ KeyValuePair& operator=(KeyValuePair<TKey, TValue>&& that)
+ {
+ key = _Move(that.key);
+ value = _Move(that.value);
+ return *this;
+ }
+ KeyValuePair& operator=(const KeyValuePair<TKey, TValue>& that)
+ {
+ key = that.key;
+ value = that.value;
+ return *this;
+ }
+ HashCode getHashCode() const
{
- return &in->second;
+ return combineHash(Slang::getHashCode(key), Slang::getHashCode(value));
}
- template <typename KEY, typename VALUE>
- SLANG_FORCE_INLINE const VALUE* getValue(const KeyValuePair<KEY, VALUE>* in)
+ bool operator==(const KeyValuePair<TKey, TValue>& that) const
{
- return &in->value;
+ return (key == that.key) && (value == that.value);
}
+};
- } // namespace KeyValueDetail
+template<typename TKey, typename TValue>
+inline KeyValuePair<TKey, TValue> KVPair(const TKey& k, const TValue& v)
+{
+ return KeyValuePair<TKey, TValue>(k, v);
+}
+
+namespace KeyValueDetail
+{
+
+template<typename KEY, typename VALUE>
+SLANG_FORCE_INLINE const KEY* getKey(const std::pair<KEY, VALUE>* in)
+{
+ return &in->first;
+}
+template<typename KEY, typename VALUE>
+SLANG_FORCE_INLINE const KEY* getKey(const KeyValuePair<KEY, VALUE>* in)
+{
+ return &in->key;
+}
+
+template<typename KEY, typename VALUE>
+SLANG_FORCE_INLINE const VALUE* getValue(const std::pair<KEY, VALUE>* in)
+{
+ return &in->second;
+}
+template<typename KEY, typename VALUE>
+SLANG_FORCE_INLINE const VALUE* getValue(const KeyValuePair<KEY, VALUE>* in)
+{
+ return &in->value;
+}
- const float kMaxLoadFactor = 0.7f;
+} // namespace KeyValueDetail
- template<typename TKey, typename TValue, typename Hash = Slang::Hash<TKey>, typename KeyEqual = std::equal_to<TKey>>
- class Dictionary
+const float kMaxLoadFactor = 0.7f;
+
+template<
+ typename TKey,
+ typename TValue,
+ typename Hash = Slang::Hash<TKey>,
+ typename KeyEqual = std::equal_to<TKey>>
+class Dictionary
+{
+ using InnerMap = ankerl::unordered_dense::map<TKey, TValue, Hash, KeyEqual>;
+ using ThisType = Dictionary<TKey, TValue, Hash, KeyEqual>;
+ InnerMap map;
+
+public:
+ Dictionary() = default;
+ Dictionary(const Dictionary&) = default;
+ Dictionary(Dictionary&&) = default;
+ ThisType& operator=(const ThisType&) = default;
+ ThisType& operator=(ThisType&&) = default;
+ Dictionary(std::initializer_list<typename InnerMap::value_type> inits)
+ : map(std::move(inits))
{
- using InnerMap = ankerl::unordered_dense::map<
- TKey,
- TValue,
- Hash,
- KeyEqual>;
- using ThisType = Dictionary<TKey, TValue, Hash, KeyEqual>;
- InnerMap map;
- public:
- Dictionary() = default;
- Dictionary(const Dictionary&) = default;
- Dictionary(Dictionary&&) = default;
- ThisType& operator=(const ThisType&) = default;
- ThisType& operator=(ThisType&&) = default;
- Dictionary(std::initializer_list<typename InnerMap::value_type> inits)
- : map(std::move(inits))
- {
- }
+ }
- //
- // Types
- //
- using Iterator = typename InnerMap::iterator;
- using ConstIterator = typename InnerMap::const_iterator;
- using KeyType = TKey;
- using ValueType = TValue;
+ //
+ // Types
+ //
+ using Iterator = typename InnerMap::iterator;
+ using ConstIterator = typename InnerMap::const_iterator;
+ using KeyType = TKey;
+ using ValueType = TValue;
- //
- // Iterators
- //
+ //
+ // Iterators
+ //
- auto begin() { return map.begin(); }
- auto begin() const { return map.begin(); }
- auto end() { return map.end(); }
- auto end() const { return map.end(); }
+ auto begin() { return map.begin(); }
+ auto begin() const { return map.begin(); }
+ auto end() { return map.end(); }
+ auto end() const { return map.end(); }
- //
- // Modifiers
- //
+ //
+ // Modifiers
+ //
- // Removes all values from the map
- void clear() { map.clear(); }
+ // Removes all values from the map
+ void clear() { map.clear(); }
- // Erases the value at the specified key if it exists
- void remove(const TKey& key) { map.erase(key); }
+ // Erases the value at the specified key if it exists
+ void remove(const TKey& key) { map.erase(key); }
- // Reserves enough space for the specified number of values
- void reserve(Index size) { map.reserve(std::size_t(size)); };
+ // Reserves enough space for the specified number of values
+ void reserve(Index size) { map.reserve(std::size_t(size)); };
- // Swap with another map
- void swapWith(ThisType& rhs) { std::swap(*this, rhs); }
+ // Swap with another map
+ void swapWith(ThisType& rhs) { std::swap(*this, rhs); }
- //
- // Query capacity
- //
+ //
+ // Query capacity
+ //
- std::size_t getCount() const { return map.size(); }
+ std::size_t getCount() const { return map.size(); }
- //
- // Lookup
- //
+ //
+ // Lookup
+ //
- // Returns true if the map contains an equivalent key
- template<typename K>
- bool containsKey(const K& k) const { return map.contains(k); }
+ // Returns true if the map contains an equivalent key
+ template<typename K>
+ bool containsKey(const K& k) const
+ {
+ return map.contains(k);
+ }
- // Returns a valid pointer to the requested element, or nullptr if it
- // doesn't exist
- template<typename K>
- const TValue* tryGetValue(const K& key) const
- {
- auto i = map.find(key);
- return i == map.end() ? nullptr : &(i->second);
- }
- // Returns a valid pointer to the requested element, or nullptr if it
- // doesn't exist
- template<typename K>
- TValue* tryGetValue(const K& key)
- {
- auto i = map.find(key);
- return i == map.end() ? nullptr : std::addressof(i->second);
- }
+ // Returns a valid pointer to the requested element, or nullptr if it
+ // doesn't exist
+ template<typename K>
+ const TValue* tryGetValue(const K& key) const
+ {
+ auto i = map.find(key);
+ return i == map.end() ? nullptr : &(i->second);
+ }
+ // Returns a valid pointer to the requested element, or nullptr if it
+ // doesn't exist
+ template<typename K>
+ TValue* tryGetValue(const K& key)
+ {
+ auto i = map.find(key);
+ return i == map.end() ? nullptr : std::addressof(i->second);
+ }
- // Returns true and copies the element into 'value' if present.
- // Otherwise returns false and value unmodified.
- template<typename K>
- bool tryGetValue(const K& key, TValue& value) const
- {
- auto i = map.find(key);
- if(i == map.end())
- return false;
- value = i->second;
- return true;
- }
+ // Returns true and copies the element into 'value' if present.
+ // Otherwise returns false and value unmodified.
+ template<typename K>
+ bool tryGetValue(const K& key, TValue& value) const
+ {
+ auto i = map.find(key);
+ if (i == map.end())
+ return false;
+ value = i->second;
+ return true;
+ }
- // Returns a const reference to the value at the given key. Asserts if
- // the value doesn't exist
- const TValue& getValue(const TKey& key) const
- {
- if(const auto x = tryGetValue(key))
- return *x;
- SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
- }
+ // Returns a const reference to the value at the given key. Asserts if
+ // the value doesn't exist
+ const TValue& getValue(const TKey& key) const
+ {
+ if (const auto x = tryGetValue(key))
+ return *x;
+ SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
+ }
- // Returns a reference to the value at the given key. Asserts if the
- // value doesn't exist
- TValue& getValue(const TKey& key)
- {
- if(const auto x = tryGetValue(key))
- return *x;
- SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
- }
+ // Returns a reference to the value at the given key. Asserts if the
+ // value doesn't exist
+ TValue& getValue(const TKey& key)
+ {
+ if (const auto x = tryGetValue(key))
+ return *x;
+ SLANG_ASSERT_FAILURE("The key does not exist in dictionary.");
+ }
- //
- // Combined Lookup and Insertion
- //
+ //
+ // Combined Lookup and Insertion
+ //
- // Tries to insert the given element, if a value was already present at
- // the given key then returns a pointer to that element instead.
- // Returns nullptr if insertion was successful.
- TValue* tryGetValueOrAdd(const typename InnerMap::value_type& kvPair)
- {
- const auto& [iterator, inserted] = map.insert(kvPair);
- return inserted ? nullptr : std::addressof(iterator->second);
- }
- // Tries to insert the given element, if a value was already present at
- // the given key then returns a pointer to that element instead.
- // Returns nullptr if insertion was successful.
- TValue* tryGetValueOrAdd(typename InnerMap::value_type&& kvPair)
- {
- const auto& [iterator, inserted] = map.insert(std::move(kvPair));
- return inserted ? nullptr : std::addressof(iterator->second);
- }
- // Tries to insert the given element, if a value was already present at
- // the given key then returns a pointer to that element instead.
- // Returns nullptr if insertion was successful.
- TValue* tryGetValueOrAdd(const TKey& key, const TValue& value) { return tryGetValueOrAdd({key, value}); }
-
- // Inserts the given value if it doesn't exist already
- // Return a reference to the (possibly new) value in the map
- TValue& getOrAddValue(const TKey& key, const TValue& defaultValue)
- {
- auto [iterator, inserted] = map.insert({key, defaultValue});
- return iterator->second;
- }
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(const typename InnerMap::value_type& kvPair)
+ {
+ const auto& [iterator, inserted] = map.insert(kvPair);
+ return inserted ? nullptr : std::addressof(iterator->second);
+ }
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(typename InnerMap::value_type&& kvPair)
+ {
+ const auto& [iterator, inserted] = map.insert(std::move(kvPair));
+ return inserted ? nullptr : std::addressof(iterator->second);
+ }
+ // Tries to insert the given element, if a value was already present at
+ // the given key then returns a pointer to that element instead.
+ // Returns nullptr if insertion was successful.
+ TValue* tryGetValueOrAdd(const TKey& key, const TValue& value)
+ {
+ return tryGetValueOrAdd({key, value});
+ }
- // Returns a reference to the value at the specified key, default
- // initializing it if it doesn't already exist
- TValue& operator[]( const TKey& key ) { return map[key]; }
- // Returns a reference to the value at the specified key, default
- // initializing it if it doesn't already exist
- TValue& operator[]( TKey&& key ) { return map[std::move(key)]; }
-
- //
- // Insertion
- //
-
- // Returns true if the value was inserted, returns false if the map
- // already has a value associated with this key
- bool addIfNotExists(typename InnerMap::value_type&& kvPair) { return !tryGetValueOrAdd(std::move(kvPair)); }
- // Returns true if the value was inserted, returns false if the map
- // already has a value associated with this key
- bool addIfNotExists(const typename InnerMap::value_type& kvPair) { return !tryGetValueOrAdd(kvPair); }
- // Returns true if the value was inserted, returns false if the map
- // already has a value associated with this key
- bool addIfNotExists(const TKey& k, const TValue& v) { return addIfNotExists({k, v}); }
- // Returns true if the value was inserted, returns false if the map
- // already has a value associated with this key
- bool addIfNotExists(TKey&& k, TValue&& v) { return addIfNotExists({std::move(k), std::move(v)}); }
-
- // Asserts if the key already exists in the dictionary
- void add(typename InnerMap::value_type&& kvPair)
- {
- if (!addIfNotExists(std::move(kvPair)))
- SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
- }
- // Asserts if the key already exists in the dictionary
- void add(const typename InnerMap::value_type& kvPair)
- {
- if (!addIfNotExists(kvPair))
- SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
- }
- // Asserts if the key already exists in the dictionary
- void add(const TKey& key, const TValue& value) { add({key, value}); }
- // Asserts if the key already exists in the dictionary
- void add(TKey&& key, TValue&& value) { add({std::move(key), std::move(value)}); }
+ // Inserts the given value if it doesn't exist already
+ // Return a reference to the (possibly new) value in the map
+ TValue& getOrAddValue(const TKey& key, const TValue& defaultValue)
+ {
+ auto [iterator, inserted] = map.insert({key, defaultValue});
+ return iterator->second;
+ }
- // Inserts into the dictionary or assigns if the key already exists
- void set(const TKey& key, const TValue& value) { map.insert_or_assign(key, value); }
- };
+ // Returns a reference to the value at the specified key, default
+ // initializing it if it doesn't already exist
+ TValue& operator[](const TKey& key) { return map[key]; }
+ // Returns a reference to the value at the specified key, default
+ // initializing it if it doesn't already exist
+ TValue& operator[](TKey&& key) { return map[std::move(key)]; }
+
+ //
+ // Insertion
+ //
+
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(typename InnerMap::value_type&& kvPair)
+ {
+ return !tryGetValueOrAdd(std::move(kvPair));
+ }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(const typename InnerMap::value_type& kvPair)
+ {
+ return !tryGetValueOrAdd(kvPair);
+ }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(const TKey& k, const TValue& v) { return addIfNotExists({k, v}); }
+ // Returns true if the value was inserted, returns false if the map
+ // already has a value associated with this key
+ bool addIfNotExists(TKey&& k, TValue&& v)
+ {
+ return addIfNotExists({std::move(k), std::move(v)});
+ }
+
+ // Asserts if the key already exists in the dictionary
+ void add(typename InnerMap::value_type&& kvPair)
+ {
+ if (!addIfNotExists(std::move(kvPair)))
+ SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
+ }
+ // Asserts if the key already exists in the dictionary
+ void add(const typename InnerMap::value_type& kvPair)
+ {
+ if (!addIfNotExists(kvPair))
+ SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
+ }
+ // Asserts if the key already exists in the dictionary
+ void add(const TKey& key, const TValue& value) { add({key, value}); }
+ // Asserts if the key already exists in the dictionary
+ void add(TKey&& key, TValue&& value) { add({std::move(key), std::move(value)}); }
+
+ // Inserts into the dictionary or assigns if the key already exists
+ void set(const TKey& key, const TValue& value) { map.insert_or_assign(key, value); }
+};
- /* We may want to rename this, as strictly speaking _Caps names are reserved */
- class _DummyClass
- {};
+/* We may want to rename this, as strictly speaking _Caps names are reserved */
+class _DummyClass
+{
+};
+
+template<typename T, typename DictionaryType>
+class HashSetBase
+{
+protected:
+ DictionaryType dict;
+
+private:
+ template<typename... Args>
+ void init(const T& v, Args... args)
+ {
+ add(v);
+ init(args...);
+ }
- template<typename T, typename DictionaryType>
- class HashSetBase
+public:
+ HashSetBase() {}
+ template<typename Arg, typename... Args>
+ HashSetBase(Arg arg, Args... args)
+ {
+ init(arg, args...);
+ }
+ HashSetBase(const HashSetBase& set) { operator=(set); }
+ HashSetBase(HashSetBase&& set) { operator=(_Move(set)); }
+ HashSetBase& operator=(const HashSetBase& set)
+ {
+ dict = set.dict;
+ return *this;
+ }
+ HashSetBase& operator=(HashSetBase&& set)
+ {
+ dict = _Move(set.dict);
+ return *this;
+ }
+
+public:
+ class Iterator
{
- protected:
- DictionaryType dict;
private:
- template<typename... Args>
- void init(const T& v, Args... args)
- {
- add(v);
- init(args...);
- }
- public:
- HashSetBase()
- {}
- template<typename Arg, typename... Args>
- HashSetBase(Arg arg, Args... args)
- {
- init(arg, args...);
- }
- HashSetBase(const HashSetBase& set)
- {
- operator=(set);
- }
- HashSetBase(HashSetBase&& set)
- {
- operator=(_Move(set));
- }
- HashSetBase& operator=(const HashSetBase& set)
- {
- dict = set.dict;
- return *this;
- }
- HashSetBase& operator=(HashSetBase&& set)
- {
- dict = _Move(set.dict);
- return *this;
- }
- public:
- class Iterator
- {
- private:
- typename DictionaryType::ConstIterator iter;
- public:
- Iterator() = default;
- const T& operator*() const
- {
- return *KeyValueDetail::getKey(std::addressof(*iter));
- }
- const T* operator->() const
- {
- return KeyValueDetail::getKey(std::addressof(*iter));
- }
+ typename DictionaryType::ConstIterator iter;
- Iterator& operator++()
- {
- ++iter;
- return *this;
- }
- Iterator operator++(int)
- {
- Iterator rs = *this;
- operator++();
- return rs;
- }
- bool operator!=(const Iterator& that) const
- {
- return iter != that.iter;
- }
- bool operator==(const Iterator& that) const
- {
- return iter == that.iter;
- }
- Iterator(const typename DictionaryType::ConstIterator& _iter)
- {
- this->iter = _iter;
- }
- };
- Iterator begin() const
- {
- return Iterator(dict.begin());
- }
- Iterator end() const
- {
- return Iterator(dict.end());
- }
public:
- auto getCount() const
- {
- return dict.getCount();
- }
- void clear()
- {
- dict.clear();
- }
- bool add(const T& obj)
- {
- return dict.addIfNotExists(obj, _DummyClass());
- }
- bool add(T&& obj)
- {
- return dict.addIfNotExists(_Move(obj), _DummyClass());
- }
- void remove(const T& obj)
+ Iterator() = default;
+ const T& operator*() const { return *KeyValueDetail::getKey(std::addressof(*iter)); }
+ const T* operator->() const { return KeyValueDetail::getKey(std::addressof(*iter)); }
+
+ Iterator& operator++()
{
- dict.remove(obj);
+ ++iter;
+ return *this;
}
- bool contains(const T& obj) const
+ Iterator operator++(int)
{
- return dict.containsKey(obj);
+ Iterator rs = *this;
+ operator++();
+ return rs;
}
+ bool operator!=(const Iterator& that) const { return iter != that.iter; }
+ bool operator==(const Iterator& that) const { return iter == that.iter; }
+ Iterator(const typename DictionaryType::ConstIterator& _iter) { this->iter = _iter; }
};
- template <typename T>
- class HashSet : public HashSetBase<T, Dictionary<T, _DummyClass>>
- {};
+ Iterator begin() const { return Iterator(dict.begin()); }
+ Iterator end() const { return Iterator(dict.end()); }
+
+public:
+ auto getCount() const { return dict.getCount(); }
+ void clear() { dict.clear(); }
+ bool add(const T& obj) { return dict.addIfNotExists(obj, _DummyClass()); }
+ bool add(T&& obj) { return dict.addIfNotExists(_Move(obj), _DummyClass()); }
+ void remove(const T& obj) { dict.remove(obj); }
+ bool contains(const T& obj) const { return dict.containsKey(obj); }
+};
+template<typename T>
+class HashSet : public HashSetBase<T, Dictionary<T, _DummyClass>>
+{
+};
- template <typename TKey, typename TValue>
- class OrderedDictionary
- {
- friend class Iterator;
- friend class ItemProxy;
+template<typename TKey, typename TValue>
+class OrderedDictionary
+{
+ friend class Iterator;
+ friend class ItemProxy;
- private:
- inline int getProbeOffset(int /*probeIdx*/) const
- {
- // quadratic probing
- return 1;
- }
+private:
+ inline int getProbeOffset(int /*probeIdx*/) const
+ {
+ // quadratic probing
+ return 1;
+ }
- private:
- int m_bucketCountMinusOne;
- int m_count;
- UIntSet m_marks;
+private:
+ int m_bucketCountMinusOne;
+ int m_count;
+ UIntSet m_marks;
- LinkedList<KeyValuePair<TKey, TValue>> m_kvPairs;
- LinkedNode<KeyValuePair<TKey, TValue>>** m_hashMap;
- void deallocateAll()
- {
- if (m_hashMap)
- delete[] m_hashMap;
- m_hashMap = nullptr;
- m_kvPairs.clear();
- }
- inline bool isDeleted(int pos) const { return m_marks.contains((pos << 1) + 1); }
- inline bool isEmpty(int pos) const { return !m_marks.contains((pos << 1)); }
- inline void setDeleted(int pos, bool val)
+ LinkedList<KeyValuePair<TKey, TValue>> m_kvPairs;
+ LinkedNode<KeyValuePair<TKey, TValue>>** m_hashMap;
+ void deallocateAll()
+ {
+ if (m_hashMap)
+ delete[] m_hashMap;
+ m_hashMap = nullptr;
+ m_kvPairs.clear();
+ }
+ inline bool isDeleted(int pos) const { return m_marks.contains((pos << 1) + 1); }
+ inline bool isEmpty(int pos) const { return !m_marks.contains((pos << 1)); }
+ inline void setDeleted(int pos, bool val)
+ {
+ if (val)
+ m_marks.add((pos << 1) + 1);
+ else
+ m_marks.remove((pos << 1) + 1);
+ }
+ inline void setEmpty(int pos, bool val)
+ {
+ if (val)
+ m_marks.remove((pos << 1));
+ else
+ m_marks.add((pos << 1));
+ }
+ struct FindPositionResult
+ {
+ int objectPosition;
+ int insertionPosition;
+ FindPositionResult()
{
- if (val)
- m_marks.add((pos << 1) + 1);
- else
- m_marks.remove((pos << 1) + 1);
+ objectPosition = -1;
+ insertionPosition = -1;
}
- inline void setEmpty(int pos, bool val)
+ FindPositionResult(int objPos, int insertPos)
{
- if (val)
- m_marks.remove((pos << 1));
- else
- m_marks.add((pos << 1));
+ objectPosition = objPos;
+ insertionPosition = insertPos;
}
- struct FindPositionResult
+ };
+ template<typename T>
+ inline int getHashPos(T& key) const
+ {
+ const unsigned int hash = (unsigned int)getHashCode(key);
+ return ((unsigned int)(hash * 2654435761)) % m_bucketCountMinusOne;
+ }
+ template<typename T>
+ FindPositionResult findPosition(const T& key) const
+ {
+ int hashPos = getHashPos((T&)key);
+ int insertPos = -1;
+ int numProbes = 0;
+ while (numProbes <= m_bucketCountMinusOne)
{
- int objectPosition;
- int insertionPosition;
- FindPositionResult()
+ if (isEmpty(hashPos))
{
- objectPosition = -1;
- insertionPosition = -1;
+ if (insertPos == -1)
+ return FindPositionResult(-1, hashPos);
+ else
+ return FindPositionResult(-1, insertPos);
}
- FindPositionResult(int objPos, int insertPos)
+ else if (isDeleted(hashPos))
{
- objectPosition = objPos;
- insertionPosition = insertPos;
+ if (insertPos == -1)
+ insertPos = hashPos;
}
- };
- template <typename T> inline int getHashPos(T& key) const
- {
- const unsigned int hash = (unsigned int)getHashCode(key);
- return ((unsigned int)(hash * 2654435761)) % m_bucketCountMinusOne;
- }
- template <typename T> FindPositionResult findPosition(const T& key) const
- {
- int hashPos = getHashPos((T&)key);
- int insertPos = -1;
- int numProbes = 0;
- while (numProbes <= m_bucketCountMinusOne)
+ else if (m_hashMap[hashPos]->value.key == key)
{
- if (isEmpty(hashPos))
- {
- if (insertPos == -1)
- return FindPositionResult(-1, hashPos);
- else
- return FindPositionResult(-1, insertPos);
- }
- else if (isDeleted(hashPos))
- {
- if (insertPos == -1)
- insertPos = hashPos;
- }
- else if (m_hashMap[hashPos]->value.key == key)
- {
- return FindPositionResult(hashPos, -1);
- }
- numProbes++;
- hashPos = (hashPos + getProbeOffset(numProbes)) & m_bucketCountMinusOne;
+ return FindPositionResult(hashPos, -1);
}
- if (insertPos != -1)
- return FindPositionResult(-1, insertPos);
- SLANG_ASSERT_FAILURE("Hash map is full. This indicates an error in Key::Equal or Key::GetHashCode.");
+ numProbes++;
+ hashPos = (hashPos + getProbeOffset(numProbes)) & m_bucketCountMinusOne;
}
- TValue& _insert(KeyValuePair<TKey, TValue>&& kvPair, int pos)
- {
- auto node = m_kvPairs.addLast();
- node->value = _Move(kvPair);
- m_hashMap[pos] = node;
- setEmpty(pos, false);
- setDeleted(pos, false);
- return node->value.value;
- }
- void maybeRehash()
+ if (insertPos != -1)
+ return FindPositionResult(-1, insertPos);
+ SLANG_ASSERT_FAILURE(
+ "Hash map is full. This indicates an error in Key::Equal or Key::GetHashCode.");
+ }
+ TValue& _insert(KeyValuePair<TKey, TValue>&& kvPair, int pos)
+ {
+ auto node = m_kvPairs.addLast();
+ node->value = _Move(kvPair);
+ m_hashMap[pos] = node;
+ setEmpty(pos, false);
+ setDeleted(pos, false);
+ return node->value.value;
+ }
+ void maybeRehash()
+ {
+ if (m_bucketCountMinusOne == -1 || m_count / (float)m_bucketCountMinusOne >= kMaxLoadFactor)
{
- if (m_bucketCountMinusOne == -1 || m_count / (float)m_bucketCountMinusOne >= kMaxLoadFactor)
+ int newSize = (m_bucketCountMinusOne + 1) * 2;
+ if (newSize == 0)
{
- int newSize = (m_bucketCountMinusOne + 1) * 2;
- if (newSize == 0)
- {
- newSize = 128;
- }
- OrderedDictionary<TKey, TValue> newDict;
- newDict.m_bucketCountMinusOne = newSize - 1;
- newDict.m_hashMap = new LinkedNode<KeyValuePair<TKey, TValue>>*[newSize];
- newDict.m_marks.resizeAndClear(newSize * 2);
- if (m_hashMap)
+ newSize = 128;
+ }
+ OrderedDictionary<TKey, TValue> newDict;
+ newDict.m_bucketCountMinusOne = newSize - 1;
+ newDict.m_hashMap = new LinkedNode<KeyValuePair<TKey, TValue>>*[newSize];
+ newDict.m_marks.resizeAndClear(newSize * 2);
+ if (m_hashMap)
+ {
+ for (auto& kvPair : *this)
{
- for (auto& kvPair : *this)
- {
- newDict.add(_Move(kvPair));
- }
+ newDict.add(_Move(kvPair));
}
- *this = _Move(newDict);
}
+ *this = _Move(newDict);
}
+ }
- bool addIfNotExists(KeyValuePair<TKey, TValue>&& kvPair)
+ bool addIfNotExists(KeyValuePair<TKey, TValue>&& kvPair)
+ {
+ maybeRehash();
+ auto pos = findPosition(kvPair.key);
+ if (pos.objectPosition != -1)
+ return false;
+ else if (pos.insertionPosition != -1)
{
- maybeRehash();
- auto pos = findPosition(kvPair.key);
- if (pos.objectPosition != -1)
- return false;
- else if (pos.insertionPosition != -1)
- {
- m_count++;
- _insert(_Move(kvPair), pos.insertionPosition);
- return true;
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
+ m_count++;
+ _insert(_Move(kvPair), pos.insertionPosition);
+ return true;
}
- void add(KeyValuePair<TKey, TValue>&& kvPair)
+ else
+ SLANG_ASSERT_FAILURE(
+ "Inconsistent find result returned. This is a bug in Dictionary implementation.");
+ }
+ void add(KeyValuePair<TKey, TValue>&& kvPair)
+ {
+ if (!addIfNotExists(_Move(kvPair)))
+ SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
+ }
+ TValue& set(KeyValuePair<TKey, TValue>&& kvPair)
+ {
+ maybeRehash();
+ auto pos = findPosition(kvPair.key);
+ if (pos.objectPosition != -1)
{
- if (!addIfNotExists(_Move(kvPair)))
- SLANG_ASSERT_FAILURE("The key already exists in Dictionary.");
+ m_hashMap[pos.objectPosition]->removeAndDelete();
+ return _insert(_Move(kvPair), pos.objectPosition);
}
- TValue& set(KeyValuePair<TKey, TValue>&& kvPair)
+ else if (pos.insertionPosition != -1)
{
- maybeRehash();
- auto pos = findPosition(kvPair.key);
- if (pos.objectPosition != -1)
- {
- m_hashMap[pos.objectPosition]->removeAndDelete();
- return _insert(_Move(kvPair), pos.objectPosition);
- }
- else if (pos.insertionPosition != -1)
- {
- m_count++;
- return _insert(_Move(kvPair), pos.insertionPosition);
- }
- else
- SLANG_ASSERT_FAILURE("Inconsistent find result returned. This is a bug in Dictionary implementation.");
+ m_count++;
+ return _insert(_Move(kvPair), pos.insertionPosition);
}
+ else
+ SLANG_ASSERT_FAILURE(
+ "Inconsistent find result returned. This is a bug in Dictionary implementation.");
+ }
- public:
- using Iterator = typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator;
- using ConstIterator = typename LinkedList<KeyValuePair<TKey, TValue>>::ConstIterator;
+public:
+ using Iterator = typename LinkedList<KeyValuePair<TKey, TValue>>::Iterator;
+ using ConstIterator = typename LinkedList<KeyValuePair<TKey, TValue>>::ConstIterator;
- Iterator begin() { return m_kvPairs.begin(); }
- Iterator end() { return m_kvPairs.end(); }
- ConstIterator begin() const { return m_kvPairs.begin(); }
- ConstIterator end() const { return m_kvPairs.end(); }
+ Iterator begin() { return m_kvPairs.begin(); }
+ Iterator end() { return m_kvPairs.end(); }
+ ConstIterator begin() const { return m_kvPairs.begin(); }
+ ConstIterator end() const { return m_kvPairs.end(); }
- public:
- void add(const TKey& key, const TValue& value)
- {
- add(KeyValuePair<TKey, TValue>(key, value));
- }
- void add(TKey&& key, TValue&& value)
- {
- add(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
- }
- bool addIfNotExists(const TKey& key, const TValue& value)
- {
- return addIfNotExists(KeyValuePair<TKey, TValue>(key, value));
- }
- bool addIfNotExists(TKey&& key, TValue&& value)
- {
- return addIfNotExists(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
- }
- void remove(const TKey& key)
- {
- if (m_count > 0)
- {
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- m_kvPairs.removeAndDelete(m_hashMap[pos.objectPosition]);
- m_hashMap[pos.objectPosition] = 0;
- setDeleted(pos.objectPosition, true);
- m_count--;
- }
- }
- }
- void clear()
- {
- m_count = 0;
- m_kvPairs.clear();
- m_marks.clear();
- }
- template <typename T> bool containsKey(const T& key) const
- {
- if (m_bucketCountMinusOne == -1)
- return false;
- auto pos = findPosition(key);
- return pos.objectPosition != -1;
- }
- template <typename T> TValue* tryGetValue(const T& key) const
+public:
+ void add(const TKey& key, const TValue& value) { add(KeyValuePair<TKey, TValue>(key, value)); }
+ void add(TKey&& key, TValue&& value)
+ {
+ add(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
+ }
+ bool addIfNotExists(const TKey& key, const TValue& value)
+ {
+ return addIfNotExists(KeyValuePair<TKey, TValue>(key, value));
+ }
+ bool addIfNotExists(TKey&& key, TValue&& value)
+ {
+ return addIfNotExists(KeyValuePair<TKey, TValue>(_Move(key), _Move(value)));
+ }
+ void remove(const TKey& key)
+ {
+ if (m_count > 0)
{
- if (m_bucketCountMinusOne == -1)
- return nullptr;
auto pos = findPosition(key);
if (pos.objectPosition != -1)
{
- return &(m_hashMap[pos.objectPosition]->value.value);
+ m_kvPairs.removeAndDelete(m_hashMap[pos.objectPosition]);
+ m_hashMap[pos.objectPosition] = 0;
+ setDeleted(pos.objectPosition, true);
+ m_count--;
}
- return nullptr;
}
- template <typename T> bool tryGetValue(const T& key, TValue& value) const
- {
- if (m_bucketCountMinusOne == -1)
- return false;
- auto pos = findPosition(key);
- if (pos.objectPosition != -1)
- {
- value = m_hashMap[pos.objectPosition]->value.value;
- return true;
- }
+ }
+ void clear()
+ {
+ m_count = 0;
+ m_kvPairs.clear();
+ m_marks.clear();
+ }
+ template<typename T>
+ bool containsKey(const T& key) const
+ {
+ if (m_bucketCountMinusOne == -1)
return false;
- }
- class ItemProxy
+ auto pos = findPosition(key);
+ return pos.objectPosition != -1;
+ }
+ template<typename T>
+ TValue* tryGetValue(const T& key) const
+ {
+ if (m_bucketCountMinusOne == -1)
+ return nullptr;
+ auto pos = findPosition(key);
+ if (pos.objectPosition != -1)
{
- private:
- const OrderedDictionary<TKey, TValue>* dict;
- TKey key;
-
- public:
- ItemProxy(const TKey& _key, const OrderedDictionary<TKey, TValue>* _dict)
- {
- this->dict = _dict;
- this->key = _key;
- }
- ItemProxy(TKey&& _key, const OrderedDictionary<TKey, TValue>* _dict)
- {
- this->dict = _dict;
- this->key = _Move(_key);
- }
- TValue& getValue() const
- {
- auto pos = dict->findPosition(key);
- if (pos.objectPosition != -1)
- {
- return dict->m_hashMap[pos.objectPosition]->value.value;
- }
- else
- {
- SLANG_ASSERT_FAILURE("The key does not exists in dictionary.");
- }
- }
- inline TValue& operator()() const { return getValue(); }
- operator TValue&() const { return getValue(); }
- TValue& operator=(const TValue& val)
- {
- return ((OrderedDictionary<TKey, TValue>*)dict)
- ->set(KeyValuePair<TKey, TValue>(_Move(key), val));
- }
- TValue& operator=(TValue&& val)
- {
- return ((OrderedDictionary<TKey, TValue>*)dict)
- ->set(KeyValuePair<TKey, TValue>(_Move(key), _Move(val)));
- }
- };
- ItemProxy operator[](const TKey& key) const { return ItemProxy(key, this); }
- ItemProxy operator[](TKey&& key) const { return ItemProxy(_Move(key), this); }
-
- int getCount() const { return m_count; }
- KeyValuePair<TKey, TValue>& getFirst() const { return m_kvPairs.getFirst(); }
- KeyValuePair<TKey, TValue>& getLast() const { return m_kvPairs.getLast(); }
-
- private:
- template <typename... Args>
- void init(const KeyValuePair<TKey, TValue>& kvPair, Args... args)
+ return &(m_hashMap[pos.objectPosition]->value.value);
+ }
+ return nullptr;
+ }
+ template<typename T>
+ bool tryGetValue(const T& key, TValue& value) const
+ {
+ if (m_bucketCountMinusOne == -1)
+ return false;
+ auto pos = findPosition(key);
+ if (pos.objectPosition != -1)
{
- add(kvPair);
- init(args...);
+ value = m_hashMap[pos.objectPosition]->value.value;
+ return true;
}
+ return false;
+ }
+ class ItemProxy
+ {
+ private:
+ const OrderedDictionary<TKey, TValue>* dict;
+ TKey key;
public:
- OrderedDictionary()
- {
- m_bucketCountMinusOne = -1;
- m_count = 0;
- m_hashMap = 0;
- }
- template <typename Arg, typename... Args> OrderedDictionary(Arg arg, Args... args)
+ ItemProxy(const TKey& _key, const OrderedDictionary<TKey, TValue>* _dict)
{
- init(arg, args...);
+ this->dict = _dict;
+ this->key = _key;
}
- OrderedDictionary(const OrderedDictionary<TKey, TValue>& other)
- : m_bucketCountMinusOne(-1)
- , m_count(0)
- , m_hashMap(0)
+ ItemProxy(TKey&& _key, const OrderedDictionary<TKey, TValue>* _dict)
{
- *this = other;
+ this->dict = _dict;
+ this->key = _Move(_key);
}
- OrderedDictionary(OrderedDictionary<TKey, TValue>&& other)
- : m_bucketCountMinusOne(-1)
- , m_count(0)
- , m_hashMap(0)
+ TValue& getValue() const
{
- *this = (_Move(other));
+ auto pos = dict->findPosition(key);
+ if (pos.objectPosition != -1)
+ {
+ return dict->m_hashMap[pos.objectPosition]->value.value;
+ }
+ else
+ {
+ SLANG_ASSERT_FAILURE("The key does not exists in dictionary.");
+ }
}
- OrderedDictionary<TKey, TValue>&
- operator=(const OrderedDictionary<TKey, TValue>& other)
+ inline TValue& operator()() const { return getValue(); }
+ operator TValue&() const { return getValue(); }
+ TValue& operator=(const TValue& val)
{
- if (this == &other)
- return *this;
- clear();
- for (auto& item : other)
- add(item.key, item.value);
- return *this;
+ return ((OrderedDictionary<TKey, TValue>*)dict)
+ ->set(KeyValuePair<TKey, TValue>(_Move(key), val));
}
- OrderedDictionary<TKey, TValue>&
- operator=(OrderedDictionary<TKey, TValue>&& other)
+ TValue& operator=(TValue&& val)
{
- if (this == &other)
- return *this;
- deallocateAll();
- m_bucketCountMinusOne = other.m_bucketCountMinusOne;
- m_count = other.m_count;
- m_hashMap = other.m_hashMap;
- m_marks = _Move(other.m_marks);
- other.m_hashMap = 0;
- other.m_count = 0;
- other.m_bucketCountMinusOne = -1;
- m_kvPairs = _Move(other.m_kvPairs);
- return *this;
+ return ((OrderedDictionary<TKey, TValue>*)dict)
+ ->set(KeyValuePair<TKey, TValue>(_Move(key), _Move(val)));
}
- ~OrderedDictionary() { deallocateAll(); }
};
+ ItemProxy operator[](const TKey& key) const { return ItemProxy(key, this); }
+ ItemProxy operator[](TKey&& key) const { return ItemProxy(_Move(key), this); }
- template <typename T> class OrderedHashSet : public HashSetBase<T, OrderedDictionary<T, _DummyClass>>
+ int getCount() const { return m_count; }
+ KeyValuePair<TKey, TValue>& getFirst() const { return m_kvPairs.getFirst(); }
+ KeyValuePair<TKey, TValue>& getLast() const { return m_kvPairs.getLast(); }
+
+private:
+ template<typename... Args>
+ void init(const KeyValuePair<TKey, TValue>& kvPair, Args... args)
{
- public:
- T& getLast()
- {
- return this->dict.getLast().key;
- }
- void removeLast()
- {
- this->remove(getLast());
- }
- };
-}
+ add(kvPair);
+ init(args...);
+ }
+
+public:
+ OrderedDictionary()
+ {
+ m_bucketCountMinusOne = -1;
+ m_count = 0;
+ m_hashMap = 0;
+ }
+ template<typename Arg, typename... Args>
+ OrderedDictionary(Arg arg, Args... args)
+ {
+ init(arg, args...);
+ }
+ OrderedDictionary(const OrderedDictionary<TKey, TValue>& other)
+ : m_bucketCountMinusOne(-1), m_count(0), m_hashMap(0)
+ {
+ *this = other;
+ }
+ OrderedDictionary(OrderedDictionary<TKey, TValue>&& other)
+ : m_bucketCountMinusOne(-1), m_count(0), m_hashMap(0)
+ {
+ *this = (_Move(other));
+ }
+ OrderedDictionary<TKey, TValue>& operator=(const OrderedDictionary<TKey, TValue>& other)
+ {
+ if (this == &other)
+ return *this;
+ clear();
+ for (auto& item : other)
+ add(item.key, item.value);
+ return *this;
+ }
+ OrderedDictionary<TKey, TValue>& operator=(OrderedDictionary<TKey, TValue>&& other)
+ {
+ if (this == &other)
+ return *this;
+ deallocateAll();
+ m_bucketCountMinusOne = other.m_bucketCountMinusOne;
+ m_count = other.m_count;
+ m_hashMap = other.m_hashMap;
+ m_marks = _Move(other.m_marks);
+ other.m_hashMap = 0;
+ other.m_count = 0;
+ other.m_bucketCountMinusOne = -1;
+ m_kvPairs = _Move(other.m_kvPairs);
+ return *this;
+ }
+ ~OrderedDictionary() { deallocateAll(); }
+};
+
+template<typename T>
+class OrderedHashSet : public HashSetBase<T, OrderedDictionary<T, _DummyClass>>
+{
+public:
+ T& getLast() { return this->dict.getLast().key; }
+ void removeLast() { this->remove(getLast()); }
+};
+} // namespace Slang
#endif