#pragma once #include #define FNV32INIT 2166136261U #define FNV32PRIME 16777619U #define FNV64INIT ULL(14695981039346656037) #define FNV64PRIME ULL(1099511628211) namespace NFnvPrivate { template constexpr ui32 FnvHash32(It b, It e, ui32 init) { while (b != e) { init = (init * FNV32PRIME) ^ (unsigned char)*b++; } return init; } template constexpr ui64 FnvHash64(It b, It e, ui64 init) { while (b != e) { init = (init * FNV64PRIME) ^ (unsigned char)*b++; } return init; } template struct TFnvHelper; #define DEF_FNV(t) \ template <> \ struct TFnvHelper { \ static const ui##t Init = FNV##t##INIT; \ template \ static constexpr ui##t FnvHash(It b, It e, ui##t init) { \ return FnvHash##t(b, e, init); \ } \ }; DEF_FNV(32) DEF_FNV(64) #undef DEF_FNV } template static constexpr T FnvHash(It b, It e, T init) { static_assert(sizeof(*b) == 1, "expect sizeof(*b) == 1"); return (T)NFnvPrivate::TFnvHelper<8 * sizeof(T)>::FnvHash(b, e, init); } template static constexpr T FnvHash(It b, It e) { return FnvHash(b, e, (T)NFnvPrivate::TFnvHelper<8 * sizeof(T)>::Init); } template static constexpr T FnvHash(const void* buf, size_t len, T init) { return FnvHash((const unsigned char*)buf, (const unsigned char*)buf + len, init); } template static constexpr T FnvHash(const void* buf, size_t len) { return FnvHash((const unsigned char*)buf, (const unsigned char*)buf + len); } template static constexpr T FnvHash(const Buf& buf) { return FnvHash(buf.data(), buf.size() * sizeof(*buf.data())); }