// Copyright 2022 The Dawn & Tint Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_ #define SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_ #include <algorithm> #include <functional> #include <optional> #include <tuple> #include <utility> #include "src/tint/utils/containers/vector.h" #include "src/tint/utils/ice/ice.h" #include "src/tint/utils/math/hash.h" #include "src/tint/utils/math/math.h" #include "src/tint/utils/memory/aligned_storage.h" #include "src/tint/utils/traits/traits.h" namespace tint { /// HashmapKey wraps the comparator type for a Hashmap and Hashset. /// HashmapKey acts like a read-only `T`, but can be reassigned so long as the value is equivalent. /// @tparam T the key comparator type. /// @tparam HASH the hash function for the key type. /// @tparam EQUAL the equality function for the key type. template <typename T, typename HASH = Hasher<T>, typename EQUAL = std::equal_to<T>> class HashmapKey { T value_; public: /// Key is an alias to this templated class. using Key = HashmapKey<T, HASH, EQUAL>; /// Hash is an alias to the hash function for the key type. using Hash = HASH; /// Equal is an alias to the equality function for the key type. using Equal = EQUAL; /// KeyOf() returns @p key, so a HashmapKey can be used as the entry type for a Hashset. /// @param key the HashmapKey /// @return @p key static const Key& KeyOf(const Key& key) { … } /// Constructor using copied value. /// @param value the key value. HashmapKey(const T& value) : … { … } // NOLINT /// Constructor using moved value. /// @param value the key value. HashmapKey(T&& value) : … { … } // NOLINT /// Constructor using pre-computed hash and copied value. /// @param hash_ the precomputed hash of @p value /// @param value the key value HashmapKey(HashCode hash_, const T& value) : … { … } /// Constructor using pre-computed hash and moved value. /// @param hash_ the precomputed hash of @p value /// @param value the key value HashmapKey(HashCode hash_, T&& value) : … { … } /// Copy constructor HashmapKey(const HashmapKey&) = default; /// Move constructor HashmapKey(HashmapKey&&) = default; /// Destructor ~HashmapKey() = default; /// Copy-assignment operator. /// @note As a hashmap uses the HashmapKey for indexing, the new value *must* have the same hash /// value and be equal to this key. /// @param other the key to copy to this key. /// @return this HashmapKey. HashmapKey& operator=(const HashmapKey& other) { … } /// Move-assignment operator. /// @note As a hashmap uses the HashmapKey for indexing, the new value *must* have the same hash /// value and be equal to this key. /// @param other the key to move to this key. /// @return this HashmapKey. HashmapKey& operator=(HashmapKey&& other) { … } /// Equality operator /// @param other the other key. /// @return true if the hash and value of @p other are equal to this key. bool operator==(const HashmapKey& other) const { … } /// Equality operator /// @param other the other key. /// @return true if the hash of other and value of @p other are equal to this key. template <typename RHS> bool operator==(const RHS& other) const { … } /// @returns the value of the key const T& Value() const { … } /// @returns the value of the key operator const T&() const { return value_; } /// @returns the pointer to the value, or the value itself if T is a pointer. auto operator->() const { … } /// The hash of value const HashCode hash; }; /// Writes the HashmapKey to the stream. /// @param out the stream to write to /// @param key the HashmapKey to write /// @returns out so calls can be chained template <typename STREAM, typename T, typename = traits::EnableIfIsOStream<STREAM>> auto& operator<<(STREAM& out, const HashmapKey<T>& key) { … } /// HashmapBase is the base class for Hashmap and Hashset. /// @tparam ENTRY is the single record in the map. The entry type must alias 'Key' to the HashmapKey /// type, and implement the method `static HashmapKey<...> KeyOf(ENTRY)` to return the key for the /// entry. template <typename ENTRY, size_t N> class HashmapBase { … }; } // namespace tint #endif // SRC_TINT_UTILS_CONTAINERS_HASHMAP_BASE_H_