7#ifndef PXR_BASE_TF_HASH_H
8#define PXR_BASE_TF_HASH_H
15#include "pxr/base/tf/api.h"
28PXR_NAMESPACE_OPEN_SCOPE
31template <
class HashState,
class T>
32std::enable_if_t<std::is_integral<T>::value>
33TfHashAppend(HashState &h, T integral)
40template <
size_t Size>
struct Tf_SizedUnsignedInt;
41template <>
struct Tf_SizedUnsignedInt<1> {
using type = uint8_t; };
42template <>
struct Tf_SizedUnsignedInt<2> {
using type = uint16_t; };
43template <>
struct Tf_SizedUnsignedInt<4> {
using type = uint32_t; };
44template <>
struct Tf_SizedUnsignedInt<8> {
using type = uint64_t; };
47template <
class HashState,
class Enum>
48std::enable_if_t<std::is_enum<Enum>::value>
49TfHashAppend(HashState &h, Enum e)
51 h.Append(
static_cast<std::underlying_type_t<Enum>
>(e));
55template <
class HashState,
class T>
56std::enable_if_t<std::is_floating_point<T>::value>
57TfHashAppend(HashState &h, T fp)
61 typename Tf_SizedUnsignedInt<
sizeof(T)>::type intbuf = 0;
62 if (fp !=
static_cast<T
>(0)) {
63 memcpy(&intbuf, &fp,
sizeof(T));
69template <
class HashState,
class T,
class U>
71TfHashAppend(HashState &h, std::pair<T, U>
const &p)
78template <
class HashState,
class... T>
80TfHashAppend(HashState &h, std::tuple<T...>
const &t)
85 std::apply([&h](
auto const&... v) { h.Append(v...); }, t);
89template <
class HashState,
class T>
91TfHashAppend(HashState &h, std::vector<T>
const &vec)
93 static_assert(!std::is_same_v<std::remove_cv_t<T>,
bool>,
94 "Unexpected usage of vector of 'bool'."
95 "Expected explicit overload.");
96 h.AppendContiguous(vec.data(), vec.size());
100template <
class HashState>
102TfHashAppend(HashState &h, std::vector<bool>
const &vec)
104 h.Append(std::hash<std::vector<bool>>{}(vec));
110template <
class HashState,
class T,
class Compare>
112TfHashAppend(HashState& h, std::set<T, Compare>
const &elements)
114 h.AppendRange(std::begin(elements), std::end(elements));
120template <
class HashState,
class Key,
class Value,
class Compare>
122TfHashAppend(HashState& h, std::map<Key, Value, Compare>
const &elements)
124 h.AppendRange(std::begin(elements), std::end(elements));
128template <
class HashState>
130TfHashAppend(HashState &h,
const std::string& s)
132 return h.AppendContiguous(s.c_str(), s.length());
137template <
class HashState,
class T>
139TfHashAppend(HashState &h,
const T* ptr) {
140 return h.Append(
reinterpret_cast<uintptr_t
>(ptr));
149template <
class HashState>
150inline void TfHashAppend(HashState &h,
char const *ptr) =
delete;
151template <
class HashState>
152inline void TfHashAppend(HashState &h,
char *ptr) =
delete;
175template <
class HashState>
178 return h.AppendContiguous(hcstr.cstr, std::strlen(hcstr.cstr));
188template <
class HashState,
class T>
189inline auto Tf_HashImpl(HashState &h, T &&obj,
long)
190 ->
decltype(std::hash<typename std::decay<T>::type>()(
191 std::forward<T>(obj)),
void())
194 h, std::hash<
typename std::decay<T>::type>()(std::forward<T>(obj)));
198template <
class HashState,
class T>
199inline auto Tf_HashImpl(HashState &h, T &&obj, ...)
200 ->
decltype(
hash_value(std::forward<T>(obj)), void())
202 TfHashAppend(h,
hash_value(std::forward<T>(obj)));
206template <
class HashState,
class T>
207inline auto Tf_HashImpl(HashState &h, T &&obj,
int)
208 ->
decltype(TfHashAppend(h, std::forward<T>(obj)), void())
210 TfHashAppend(h, std::forward<T>(obj));
215template <
class Derived>
220 template <
class... Args>
221 void Append(Args &&... args) {
222 _AppendImpl(std::forward<Args>(args)...);
227 void AppendContiguous(T
const *elems,
size_t numElems) {
228 this->_AsDerived()._AppendContiguous(elems, numElems);
232 template <
class Iter>
233 void AppendRange(Iter f, Iter l) {
234 this->_AsDerived()._AppendRange(f, l);
238 size_t GetCode()
const {
239 return this->_AsDerived()._GetCode();
243 template <
class T,
class... Args>
244 void _AppendImpl(T &&obj, Args &&... rest) {
245 this->_AsDerived()._Append(std::forward<T>(obj));
246 _AppendImpl(std::forward<Args>(rest)...);
248 void _AppendImpl()
const {
252 Derived &_AsDerived() {
253 return *
static_cast<Derived *
>(
this);
256 Derived
const &_AsDerived()
const {
257 return *
static_cast<Derived
const *
>(
this);
262class Tf_HashState :
public Tf_HashStateAPI<Tf_HashState>
265 friend class Tf_HashStateAPI<Tf_HashState>;
269 std::enable_if_t<!std::is_integral<std::decay_t<T>>::value>
271 Tf_HashImpl(*
this, std::forward<T>(obj), 0);
276 std::enable_if_t<std::is_integral<T>::value>
283 _state = _Combine(_state, i);
289 std::enable_if_t<std::is_integral<T>::value>
290 _AppendContiguous(T
const *elems,
size_t numElems) {
291 _AppendBytes(
reinterpret_cast<char const *
>(elems),
292 numElems *
sizeof(T));
297 std::enable_if_t<!std::is_integral<T>::value>
298 _AppendContiguous(T
const *elems,
size_t numElems) {
305 template <
class Iter>
306 void _AppendRange(Iter f, Iter l) {
313 TF_API
void _AppendBytes(
char const *bytes,
size_t numBytes);
316 size_t _GetCode()
const {
324 return _SwapByteOrder(_state * 11400714819323198549ULL);
329 _SwapByteOrder(uint64_t val)
const {
331 ((val & 0xFF00000000000000u) >> 56u) |
332 ((val & 0x00FF000000000000u) >> 40u) |
333 ((val & 0x0000FF0000000000u) >> 24u) |
334 ((val & 0x000000FF00000000u) >> 8u) |
335 ((val & 0x00000000FF000000u) << 8u) |
336 ((val & 0x0000000000FF0000u) << 24u) |
337 ((val & 0x000000000000FF00u) << 40u) |
338 ((val & 0x00000000000000FFu) << 56u);
342 size_t _Combine(
size_t x,
size_t y)
const {
374 return y + x * (x + 1) / 2;
378 bool _didOne =
false;
478 decltype(Tf_HashImpl(std::declval<Tf_HashState &>(),
479 std::forward<T>(obj), 0), size_t()) {
481 Tf_HashImpl(h, std::forward<T>(obj), 0);
486 template <
class... Args>
489 _CombineImpl(h, std::forward<Args>(args)...);
494 template <
class HashState,
class T,
class... Args>
495 static void _CombineImpl(HashState &h, T &&obj, Args &&... rest) {
496 Tf_HashImpl(h, std::forward<T>(obj), 0);
497 _CombineImpl(h, std::forward<Args>(rest)...);
500 template <
class HashState>
501 static void _CombineImpl(HashState &h) {
508 size_t operator()(
const char* ptr)
const;
513 size_t operator()(
const char* ptr)
const;
518 bool operator()(
const char* lhs,
const char* rhs)
const;
521PXR_NAMESPACE_CLOSE_SCOPE
A user-extensible hashing mechanism for use with runtime hash tables.
static size_t Combine(Args &&... args)
Produce a hash code by combining the hash codes of several objects.
auto operator()(T &&obj) const -> decltype(Tf_HashImpl(std::declval< Tf_HashState & >(), std::forward< T >(obj), 0), size_t())
Produce a hash code for obj.
A structure that wraps a char pointer, indicating intent that it should be hashed as a c-style null t...
A function object that compares two c-strings for equality.
A hash function object that hashes null-terminated c-string content.
A hash function object that hashes the address of a char pointer.
TfCStrHashWrapper TfHashAsCStr(char const *cstr)
Indicate that a char pointer is intended to be hashed as a C-style null terminated string.
A file containing basic constants and definitions.
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.