#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <array>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>
#include <folly/Bits.h>
#include <folly/ConstexprMath.h>
#include <folly/Likely.h>
#include <folly/Portability.h>
#include <folly/ScopeGuard.h>
#include <folly/Traits.h>
#include <folly/functional/Invoke.h>
#include <folly/lang/Align.h>
#include <folly/lang/Assume.h>
#include <folly/lang/Exception.h>
#include <folly/lang/Pretty.h>
#include <folly/lang/SafeAssert.h>
#include <folly/portability/Builtins.h>
#include <folly/container/HeterogeneousAccess.h>
#include <folly/container/detail/F14Defaults.h>
#include <folly/container/detail/F14IntrinsicsAvailability.h>
#include <folly/container/detail/F14Mask.h>
#if __has_include(<concepts>)
#include <concepts>
#endif
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
#if FOLLY_F14_CRC_INTRINSIC_AVAILABLE
#if FOLLY_NEON
#include <arm_acle.h>
#else
#include <nmmintrin.h>
#endif
#else
#ifdef _WIN32
#include <intrin.h>
#endif
#endif
#if FOLLY_NEON
#include <arm_neon.h>
#elif FOLLY_SSE >= 2
#include <emmintrin.h>
#include <immintrin.h>
#include <xmmintrin.h>
#endif
#ifndef FOLLY_F14_PERTURB_INSERTION_ORDER
#define FOLLY_F14_PERTURB_INSERTION_ORDER …
#endif
#else
#ifndef FOLLY_F14_PERTURB_INSERTION_ORDER
#define FOLLY_F14_PERTURB_INSERTION_ORDER …
#endif
#endif
namespace folly {
struct F14TableStats { … };
namespace f14 {
namespace detail {
template <F14IntrinsicsMode>
struct F14LinkCheck { … };
template <>
struct F14LinkCheck<getF14IntrinsicsMode()> { … };
bool tlsPendingSafeInserts(std::ptrdiff_t delta = 0);
std::size_t tlsMinstdRand(std::size_t n);
#if defined(_LIBCPP_VERSION)
template <typename K, typename V, typename H>
struct StdNodeReplica { … };
#else
template <typename H>
struct StdIsFastHash : std::true_type {};
template <>
struct StdIsFastHash<std::hash<long double>> : std::false_type {};
template <typename... Args>
struct StdIsFastHash<std::hash<std::basic_string<Args...>>> : std::false_type {
};
template <typename... Args>
struct StdIsFastHash<std::hash<std::basic_string_view<Args...>>>
: std::false_type {};
template <typename K, typename V, typename H, typename Enable = void>
struct StdNodeReplica {
void* next;
V value;
};
template <typename K, typename V, typename H>
struct StdNodeReplica<
K,
V,
H,
std::enable_if_t<
!StdIsFastHash<H>::value || !is_nothrow_invocable_v<H, K>>> {
void* next;
V value;
std::size_t hash;
};
#endif
template <class Container, class Predicate>
typename Container::size_type erase_if_impl(
Container& c, Predicate& predicate) { … }
}
}
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
namespace f14 {
namespace detail {
template <typename Policy>
class F14Table;
}
}
class F14HashToken final { … };
#else
class F14HashToken final {
friend constexpr bool operator==(
F14HashToken const&, F14HashToken const&) noexcept {
return true;
}
friend constexpr bool operator!=(
F14HashToken const&, F14HashToken const&) noexcept {
return false;
}
};
#endif
#if __cpp_concepts && __has_include(<concepts>)
static_assert(std::regular<F14HashToken>);
#endif
namespace f14 {
namespace detail {
template <typename Hasher, typename Void = void>
struct ShouldAssume32BitHash : std::bool_constant<!require_sizeof<Hasher>> { … };
ShouldAssume32BitHash<Hasher, void_t<typename Hasher::folly_assume_32bit_hash>>;
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
#if FOLLY_X64 || FOLLY_AARCH64 || FOLLY_RISCV64
template <typename Hasher, typename Key>
std::pair<std::size_t, std::size_t> splitHashImpl(std::size_t hash) { … }
#else
template <typename Hasher, typename Key>
std::pair<std::size_t, std::size_t> splitHashImpl(std::size_t hash) {
static_assert(sizeof(std::size_t) == sizeof(uint32_t), "");
uint8_t tag;
if (!IsAvalanchingHasher<Hasher, Key>::value) {
#if FOLLY_F14_CRC_INTRINSIC_AVAILABLE
#if FOLLY_SSE_PREREQ(4, 2)
auto c = _mm_crc32_u32(0, hash);
tag = static_cast<uint8_t>(~(c >> 25));
hash += c;
#else
auto c = __crc32cw(0, hash);
tag = static_cast<uint8_t>(~(c >> 25));
hash += c;
#endif
#else
hash ^= hash >> 13;
hash *= 0x5bd1e995;
hash ^= hash >> 15;
tag = static_cast<uint8_t>(~(hash >> 25));
#endif
} else {
tag = (hash >> 24) | 0x80;
}
return std::make_pair(hash, tag);
}
#endif
#endif
}
}
template <typename TKeyType, typename Hasher = f14::DefaultHasher<TKeyType>>
class F14HashedKey final {
public:
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
template <typename... Args>
explicit F14HashedKey(Args&&... args)
: key_(std::forward<Args>(args)...),
hash_(f14::detail::splitHashImpl<Hasher, TKeyType>(Hasher{ … }
#else
F14HashedKey() = delete;
#endif
const TKeyType& getKey() const { … }
const F14HashToken& getHashToken() const { … }
operator const TKeyType&() const { return key_; }
explicit operator const F14HashToken&() const { return hash_; }
bool operator==(const F14HashedKey& other) const { … }
bool operator==(const TKeyType& other) const { … }
private:
TKeyType key_;
F14HashToken hash_;
};
#if FOLLY_F14_VECTOR_INTRINSICS_AVAILABLE
namespace f14 {
namespace detail {
VoidDefault;
Defaulted;
template <typename T>
FOLLY_ALWAYS_INLINE static void prefetchAddr(T const* ptr) { … }
#if FOLLY_NEON
TagVector;
#elif FOLLY_SSE >= 2
using TagVector = __m128i;
#elif FOLLY_HAVE_INT128_T
using TagVector = __uint128_t;
#endif
constexpr std::size_t kRequiredVectorAlignment = …;
EmptyTagVectorType;
FOLLY_EXPORT extern EmptyTagVectorType kEmptyTagVector;
template <typename ItemType>
struct alignas(kRequiredVectorAlignment) F14Chunk { … };
template <typename Ptr>
class PackedChunkItemPtr { … };
PackedChunkItemPtr<T *>;
template <typename ChunkPtr>
class F14ItemIter { … };
struct PackedSizeAndChunkShift { … };
struct UnpackedSizeAndChunkShift { … };
SizeAndChunkShift;
template <typename ItemIter, bool EnablePackedItemIter>
struct SizeAndChunkShiftAndPackedBegin { … };
SizeAndChunkShiftAndPackedBegin<ItemIter, false>;
template <typename Policy>
class F14Table : public Policy { … };
}
}
#endif
namespace f14 {
namespace test {
inline void disableInsertOrderRandomization() { … }
}
}
}