libs/base/src/base/hash.string.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "base/ints.h" | ||
| 4 | |||
| 5 | #include <string_view> | ||
| 6 | #include <string> | ||
| 7 | #include <unordered_map> | ||
| 8 | |||
| 9 | // 1 = include text in hash, 0=don't | ||
| 10 | // todo(Gustav): move to a config instead | ||
| 11 | #define USE_HASH_TEXT 1 | ||
| 12 | |||
| 13 | namespace eu | ||
| 14 | { | ||
| 15 | |||
| 16 | /// fnv-1a hash. | ||
| 17 | /// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function | ||
| 18 | 100 | constexpr u64 hash64(const std::string_view str, u64 hash = 0xcbf29ce484222325) | |
| 19 | 100 | { return str.empty() ? hash : hash64(str.substr(1), (hash ^ str[0]) * 0x100000001b3); } | |
| 20 | |||
| 21 | /// Hash of a non-owning string. | ||
| 22 | /// It will be (pretty) printed as the original string if that is enabled. | ||
| 23 | /// Treat it as a regular `std::string_view` but without the string functionality. | ||
| 24 | /// @see \ref hash64 | ||
| 25 | /// @see \ref HshO | ||
| 26 | struct Hsh | ||
| 27 | { | ||
| 28 | /// The actual hash. | ||
| 29 | /// Prefer to use operators on \ref Hsh instead of accessing this directly. | ||
| 30 | u64 hash; | ||
| 31 | |||
| 32 | #if USE_HASH_TEXT == 1 | ||
| 33 | /// Non-owning storage of the printable string, if enabled. | ||
| 34 | /// Please ignore if possible and just print as normal. | ||
| 35 | std::string_view text; | ||
| 36 | #endif | ||
| 37 | |||
| 38 | /// Creates a new hash object and computes the hash at compile time if possible. | ||
| 39 | 2 | constexpr Hsh(const std::string_view s) | |
| 40 | 2 | : hash( hash64(s) ) | |
| 41 | #if USE_HASH_TEXT == 1 | ||
| 42 | 2 | , text(s) | |
| 43 | #endif | ||
| 44 | 2 | { } | |
| 45 | }; | ||
| 46 | |||
| 47 | /// Hash of an owning string. | ||
| 48 | /// It will be (pretty) printed as the original string if that is enabled. | ||
| 49 | /// Treat it as a regular `std::string` but without the string functionality. | ||
| 50 | /// @see \ref hash64 | ||
| 51 | /// @see \ref Hsh | ||
| 52 | struct HshO | ||
| 53 | { | ||
| 54 | /// The actual hash. | ||
| 55 | /// Prefer to use operators on \ref HshO instead of accessing this directly. | ||
| 56 | u64 hash; | ||
| 57 | |||
| 58 | #if USE_HASH_TEXT == 1 | ||
| 59 | /// Owning storage of the printable string, if enabled. | ||
| 60 | /// Please ignore if possible and just print as normal. | ||
| 61 | std::string text; | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /// Creates a new hash object and computes the hash at compile time if possible. | ||
| 65 | 1 | constexpr HshO(const std::string& s) | |
| 66 | 1 | : hash(hash64(s)) | |
| 67 | #if USE_HASH_TEXT == 1 | ||
| 68 | 1 | , text(s) | |
| 69 | #endif | ||
| 70 | 1 | { } | |
| 71 | |||
| 72 | /// Creates a new hash object and computes the hash at compile time if possible. | ||
| 73 | 13 | constexpr HshO(const std::string_view& s) | |
| 74 | 13 | : hash(hash64(s)) | |
| 75 | #if USE_HASH_TEXT == 1 | ||
| 76 | 26 | , text(s) | |
| 77 | #endif | ||
| 78 | 13 | { } | |
| 79 | |||
| 80 | /// Copy data from a non-owning hash. | ||
| 81 | 33 | constexpr HshO(const Hsh& o) | |
| 82 | 33 | : hash(o.hash) | |
| 83 | #if USE_HASH_TEXT == 1 | ||
| 84 | 66 | , text(o.text) | |
| 85 | #endif | ||
| 86 | 33 | { } | |
| 87 | }; | ||
| 88 | |||
| 89 | #define OP(op) \ | ||
| 90 | constexpr bool operator op(const Hsh& lhs, const Hsh& rhs)\ | ||
| 91 | { return lhs.hash op rhs.hash; }\ | ||
| 92 | constexpr bool operator op(const HshO& lhs, const Hsh& rhs)\ | ||
| 93 | { return lhs.hash op rhs.hash; }\ | ||
| 94 | constexpr bool operator op(const Hsh& lhs, const HshO& rhs)\ | ||
| 95 | { return lhs.hash op rhs.hash; }\ | ||
| 96 | constexpr bool operator op(const HshO& lhs, const HshO& rhs)\ | ||
| 97 | { return lhs.hash op rhs.hash; } | ||
| 98 | 78 | OP(==) OP(!=) OP(<) OP(>) OP(<=) OP(>=) | |
| 99 | #undef OP | ||
| 100 | |||
| 101 | |||
| 102 | std::string string_from(const Hsh h); | ||
| 103 | std::string string_from(const HshO& h); | ||
| 104 | |||
| 105 | |||
| 106 | ADD_CATCH_FORMATTER_DEF(Hsh) | ||
| 107 | ADD_CATCH_FORMATTER_DEF(HshO) | ||
| 108 | } | ||
| 109 | |||
| 110 | 2 | ADD_DEFAULT_FORMATTER(eu::Hsh, std::string, eu::string_from); | |
| 111 | 2 | ADD_DEFAULT_FORMATTER(eu::HshO, std::string, eu::string_from); | |
| 112 | |||
| 113 | |||
| 114 | namespace std | ||
| 115 | { | ||
| 116 | |||
| 117 | /// \private | ||
| 118 | template <> struct hash<eu::Hsh> | ||
| 119 | { | ||
| 120 | 4 | std::size_t operator()(const eu::Hsh& x) const | |
| 121 | 4 | { return x.hash; } | |
| 122 | }; | ||
| 123 | |||
| 124 | /// \private | ||
| 125 | template <> struct hash<eu::HshO> | ||
| 126 | { | ||
| 127 | 20 | std::size_t operator()(const eu::HshO& x) const | |
| 128 | 20 | { return x.hash; } | |
| 129 | }; | ||
| 130 | |||
| 131 | } | ||
| 132 |