blob: 37cc6527a42907022ebce025c2177b204dffad28 [file] [log] [blame]
/*
* Copyright (C) 2022 Apple Inc. All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
*/
#pragma once
#include <variant>
#include <wtf/Forward.h>
#include <wtf/HashTraits.h>
namespace WTF {
template<typename Key, typename HashArg = DefaultHash<Key>>
class GenericHashKey final {
WTF_MAKE_FAST_ALLOCATED;
struct EmptyKey { };
struct DeletedKey { };
public:
constexpr GenericHashKey(Key&& key)
: m_value(std::in_place_type_t<Key>(), WTFMove(key))
{
}
template<typename K>
constexpr GenericHashKey(K&& key)
: m_value(std::in_place_type_t<Key>(), std::forward<K>(key))
{
}
constexpr GenericHashKey(HashTableEmptyValueType)
: m_value(EmptyKey { })
{
}
constexpr GenericHashKey(HashTableDeletedValueType)
: m_value(DeletedKey { })
{
}
constexpr const Key& key() const { return std::get<Key>(m_value); }
constexpr unsigned hash() const
{
ASSERT_UNDER_CONSTEXPR_CONTEXT(!isHashTableDeletedValue() && !isHashTableEmptyValue());
return HashArg::hash(key());
}
constexpr bool isHashTableDeletedValue() const { return std::holds_alternative<DeletedKey>(m_value); }
constexpr bool isHashTableEmptyValue() const { return std::holds_alternative<EmptyKey>(m_value); }
constexpr bool operator==(const GenericHashKey& other) const
{
if (m_value.index() != other.m_value.index())
return false;
if (!std::holds_alternative<Key>(m_value))
return true;
return HashArg::equal(key(), other.key());
}
constexpr bool operator!=(const GenericHashKey& other) const
{
return !(*this == other);
}
private:
std::variant<Key, EmptyKey, DeletedKey> m_value;
};
template<typename K, typename H> struct HashTraits<GenericHashKey<K, H>> : GenericHashTraits<GenericHashKey<K, H>> {
static GenericHashKey<K, H> emptyValue() { return GenericHashKey<K, H> { HashTableEmptyValue }; }
static void constructDeletedValue(GenericHashKey<K, H>& slot) { slot = GenericHashKey<K, H> { HashTableDeletedValue }; }
static bool isDeletedValue(const GenericHashKey<K, H>& value) { return value.isHashTableDeletedValue(); }
};
template<typename K, typename H> struct DefaultHash<GenericHashKey<K, H>> {
static unsigned hash(const GenericHashKey<K, H>& key) { return key.hash(); }
static bool equal(const GenericHashKey<K, H>& a, const GenericHashKey<K, H>& b) { return a == b; }
static constexpr bool safeToCompareToEmptyOrDeleted = false;
};
}
using WTF::GenericHashKey;