24 #ifndef PXR_BASE_TF_HASH_H 25 #define PXR_BASE_TF_HASH_H 32 #include "pxr/base/tf/api.h" 36 #include <type_traits> 40 PXR_NAMESPACE_OPEN_SCOPE
43 template <
class HashState,
class T>
44 std::enable_if_t<std::is_integral<T>::value>
45 TfHashAppend(HashState &h, T integral)
52 template <
size_t Size>
struct Tf_SizedUnsignedInt;
53 template <>
struct Tf_SizedUnsignedInt<1> {
using type = uint8_t; };
54 template <>
struct Tf_SizedUnsignedInt<2> {
using type = uint16_t; };
55 template <>
struct Tf_SizedUnsignedInt<4> {
using type = uint32_t; };
56 template <>
struct Tf_SizedUnsignedInt<8> {
using type = uint64_t; };
59 template <
class HashState,
class Enum>
60 std::enable_if_t<std::is_enum<Enum>::value>
61 TfHashAppend(HashState &h, Enum e)
63 h.Append(
static_cast<std::underlying_type_t<Enum>
>(e));
67 template <
class HashState,
class T>
68 std::enable_if_t<std::is_floating_point<T>::value>
69 TfHashAppend(HashState &h, T fp)
73 typename Tf_SizedUnsignedInt<
sizeof(T)>::type intbuf = 0;
74 if (fp != static_cast<T>(0)) {
75 memcpy(&intbuf, &fp,
sizeof(T));
81 template <
class HashState,
class T,
class U>
83 TfHashAppend(HashState &h, std::pair<T, U>
const &p)
90 template <
class HashState,
class T>
92 TfHashAppend(HashState &h, std::vector<T>
const &vec)
94 h.AppendContiguous(vec.data(), vec.size());
98 template <
class HashState>
100 TfHashAppend(HashState &h,
const std::string& s)
102 return h.AppendContiguous(s.c_str(), s.length());
107 template <
class HashState,
class T>
109 TfHashAppend(HashState &h,
const T* ptr) {
110 return h.Append(reinterpret_cast<uintptr_t>(ptr));
119 template <
class HashState>
120 inline void TfHashAppend(HashState &h,
char const *ptr) =
delete;
121 template <
class HashState>
122 inline void TfHashAppend(HashState &h,
char *ptr) =
delete;
145 template <
class HashState>
148 return h.AppendContiguous(hcstr.cstr, std::strlen(hcstr.cstr));
173 template <
class HashState,
class T>
174 inline auto Tf_HashImpl(HashState &h, T &&obj,
long)
175 -> decltype(
hash_value(std::forward<T>(obj)),
void())
177 TfHashAppend(h,
hash_value(std::forward<T>(obj)));
181 template <
class HashState,
class T>
182 inline auto Tf_HashImpl(HashState &h, T &&obj,
int)
183 -> decltype(TfHashAppend(h, std::forward<T>(obj)),
void())
185 TfHashAppend(h, std::forward<T>(obj));
190 template <
class Derived>
191 class Tf_HashStateAPI
195 template <
class... Args>
196 void Append(Args &&... args) {
197 _AppendImpl(args...);
202 void AppendContiguous(T
const *elems,
size_t numElems) {
203 this->_AsDerived()._AppendContiguous(elems, numElems);
207 template <
class Iter>
208 void AppendRange(Iter f, Iter l) {
209 this->_AsDerived()._AppendRange(f, l);
213 size_t GetCode()
const {
214 return this->_AsDerived()._GetCode();
218 template <
class T,
class... Args>
219 void _AppendImpl(T &&obj, Args &&... rest) {
220 this->_AsDerived()._Append(std::forward<T>(obj));
221 _AppendImpl(rest...);
223 void _AppendImpl()
const {
227 Derived &_AsDerived() {
228 return *static_cast<Derived *>(
this);
231 Derived
const &_AsDerived()
const {
232 return *static_cast<Derived const *>(
this);
237 class Tf_HashState :
public Tf_HashStateAPI<Tf_HashState>
240 friend class Tf_HashStateAPI<Tf_HashState>;
244 std::enable_if_t<!std::is_integral<std::decay_t<T>>::value>
246 Tf_HashImpl(*
this, std::forward<T>(obj), 0);
251 std::enable_if_t<std::is_integral<T>::value>
258 _state = _Combine(_state, i);
264 std::enable_if_t<std::is_integral<T>::value>
265 _AppendContiguous(T
const *elems,
size_t numElems) {
266 _AppendBytes(reinterpret_cast<char const *>(elems),
267 numElems *
sizeof(T));
272 std::enable_if_t<!std::is_integral<T>::value>
273 _AppendContiguous(T
const *elems,
size_t numElems) {
280 template <
class Iter>
281 void _AppendRange(Iter f, Iter l) {
288 TF_API
void _AppendBytes(
char const *bytes,
size_t numBytes);
291 size_t _GetCode()
const {
299 return _SwapByteOrder(_state * 11400714819323198549ULL);
304 _SwapByteOrder(uint64_t val)
const {
306 ((val & 0xFF00000000000000u) >> 56u) |
307 ((val & 0x00FF000000000000u) >> 40u) |
308 ((val & 0x0000FF0000000000u) >> 24u) |
309 ((val & 0x000000FF00000000u) >> 8u) |
310 ((val & 0x00000000FF000000u) << 8u) |
311 ((val & 0x0000000000FF0000u) << 24u) |
312 ((val & 0x000000000000FF00u) << 40u) |
313 ((val & 0x00000000000000FFu) << 56u);
317 size_t _Combine(
size_t x,
size_t y)
const {
349 return y + x * (x + 1) / 2;
353 bool _didOne =
false;
453 decltype(Tf_HashImpl(std::declval<Tf_HashState &>(),
454 std::forward<T>(obj), 0),
size_t()) {
456 Tf_HashImpl(h, std::forward<T>(obj), 0);
461 template <
class... Args>
464 _CombineImpl(h, args...);
469 template <
class HashState,
class T,
class... Args>
470 static void _CombineImpl(HashState &h, T &&obj, Args &&... rest) {
471 Tf_HashImpl(h, std::forward<T>(obj), 0);
472 _CombineImpl(h, rest...);
475 template <
class HashState>
476 static void _CombineImpl(HashState &h) {
483 size_t operator()(
const char* ptr)
const;
488 size_t operator()(
const char* ptr)
const;
493 bool operator()(
const char* lhs,
const char* rhs)
const;
496 PXR_NAMESPACE_CLOSE_SCOPE
A hash function object that hashes the address of a char pointer.
A structure that wraps a char pointer, indicating intent that it should be hashed as a c-style null t...
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 hash function object that hashes null-terminated c-string content.
A function object that compares two c-strings for equality.
std::enable_if< std::is_same< Half, half >::value, size_t >::type hash_value(const Half &h)
Overload hash_value for half.
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.