fsm
hashed_string.h
1 
2 #pragma once
3 
4 #include <cstddef>
5 #include <cstdint>
6 #include "forwards.h"
7 
8 namespace escad {
9 
15 namespace details {
16 
17 template<typename>
18 struct fnv1a_traits;
19 
20 template<>
21 struct fnv1a_traits<std::uint32_t> {
22  using type = std::uint32_t;
23  static constexpr std::uint32_t offset = 2166136261;
24  static constexpr std::uint32_t prime = 16777619;
25 };
26 
27 template<>
28 struct fnv1a_traits<std::uint64_t> {
29  using type = std::uint64_t;
30  static constexpr std::uint64_t offset = 14695981039346656037ull;
31  static constexpr std::uint64_t prime = 1099511628211ull;
32 };
33 
34 template<typename Char>
35 struct basic_hashed_string {
36  using value_type = Char;
37  using size_type = std::size_t;
38  using hash_type = id_type;
39 
40  const value_type *repr;
41  size_type length;
42  hash_type hash;
43 };
44 
45 } // namespace details
46 
67 template<typename Char>
68 class basic_hashed_string: details::basic_hashed_string<Char> {
69  using base_type = details::basic_hashed_string<Char>;
70  using hs_traits = details::fnv1a_traits<id_type>;
71 
72  struct const_wrapper {
73  // non-explicit constructor on purpose
74  constexpr const_wrapper(const Char *str) noexcept
75  : repr{str} {}
76 
77  const Char *repr;
78  };
79 
80  // Fowler–Noll–Vo hash function v. 1a - the good
81  [[nodiscard]] static constexpr auto helper(const Char *str) noexcept {
82  base_type base{str, 0u, hs_traits::offset};
83 
84  for(; str[base.length]; ++base.length) {
85  base.hash = (base.hash ^ static_cast<hs_traits::type>(str[base.length])) * hs_traits::prime;
86  }
87 
88  return base;
89  }
90 
91  // Fowler–Noll–Vo hash function v. 1a - the good
92  [[nodiscard]] static constexpr auto helper(const Char *str, const std::size_t len) noexcept {
93  base_type base{str, len, hs_traits::offset};
94 
95  for(size_type pos{}; pos < len; ++pos) {
96  base.hash = (base.hash ^ static_cast<hs_traits::type>(str[pos])) * hs_traits::prime;
97  }
98 
99  return base;
100  }
101 
102 public:
104  using value_type = typename base_type::value_type;
106  using size_type = typename base_type::size_type;
108  using hash_type = typename base_type::hash_type;
109 
116  [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
117  return basic_hashed_string{str, len};
118  }
119 
126  template<std::size_t N>
127  [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) noexcept {
128  return basic_hashed_string{str};
129  }
130 
136  [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
137  return basic_hashed_string{wrapper};
138  }
139 
141  constexpr basic_hashed_string() noexcept
142  : base_type{} {}
143 
149  constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
150  : base_type{helper(str, len)} {}
151 
157  template<std::size_t N>
158  constexpr basic_hashed_string(const value_type (&str)[N]) noexcept
159  : base_type{helper(str)} {}
160 
170  explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
171  : base_type{helper(wrapper.repr)} {}
172 
177  [[nodiscard]] constexpr size_type size() const noexcept {
178  return base_type::length;
179  }
180 
185  [[nodiscard]] constexpr const value_type *data() const noexcept {
186  return base_type::repr;
187  }
188 
193  [[nodiscard]] constexpr hash_type value() const noexcept {
194  return base_type::hash;
195  }
196 
198  [[nodiscard]] constexpr operator const value_type *() const noexcept {
199  return data();
200  }
201 
206  [[nodiscard]] constexpr operator hash_type() const noexcept {
207  return value();
208  }
209 };
210 
217 template<typename Char>
218 basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>;
219 
226 template<typename Char, std::size_t N>
227 basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
228 
236 template<typename Char>
237 [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
238  return lhs.value() == rhs.value();
239 }
240 
248 template<typename Char>
249 [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
250  return !(lhs == rhs);
251 }
252 
260 template<typename Char>
261 [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
262  return lhs.value() < rhs.value();
263 }
264 
273 template<typename Char>
274 [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
275  return !(rhs < lhs);
276 }
277 
286 template<typename Char>
287 [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
288  return rhs < lhs;
289 }
290 
299 template<typename Char>
300 [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
301  return !(lhs < rhs);
302 }
303 
306 
309 
310 inline namespace literals {
311 
317 [[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) noexcept {
318  return hashed_string{str};
319 }
320 
326 [[nodiscard]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) noexcept {
327  return hashed_wstring{str};
328 }
329 
330 } // namespace literals
331 
332 } // namespace base
333 
constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
Constructs a hashed string from a string view.
Definition: hashed_string.h:149
constexpr basic_hashed_string(const_wrapper wrapper) noexcept
Explicit constructor on purpose to avoid constructing a hashed string directly from a const value_typ...
Definition: hashed_string.h:170
static constexpr hash_type value(const value_type *str, const size_type len) noexcept
Returns directly the numeric representation of a string view.
Definition: hashed_string.h:116
constexpr basic_hashed_string() noexcept
Constructs an empty hashed string.
Definition: hashed_string.h:141
typename base_type::hash_type hash_type
Unsigned integer type.
Definition: hashed_string.h:108
typename base_type::value_type value_type
Character type.
Definition: hashed_string.h:104
constexpr basic_hashed_string(const value_type(&str)[N]) noexcept
Constructs a hashed string from an array of const characters.
Definition: hashed_string.h:158
constexpr size_type size() const noexcept
Returns the size a hashed string.
Definition: hashed_string.h:177
constexpr const value_type * data() const noexcept
Returns the human-readable representation of a hashed string.
Definition: hashed_string.h:185
Definition: compressed_pair.h:255
typename base_type::size_type size_type
Unsigned integer type.
Definition: hashed_string.h:106
Zero overhead unique identifier.
Definition: hashed_string.h:68
static constexpr hash_type value(const value_type(&str)[N]) noexcept
Returns directly the numeric representation of a string.
Definition: hashed_string.h:127
Definition: compressed_pair.h:10
constexpr hash_type value() const noexcept
Returns the numeric representation of a hashed string.
Definition: hashed_string.h:193
static constexpr hash_type value(const_wrapper wrapper) noexcept
Returns directly the numeric representation of a string.
Definition: hashed_string.h:136