sandbox
Loading...
Searching...
No Matches
hashed_string.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_UTILITY_HASHED_STRING_HPP_
3#define LIBSBX_UTILITY_HASHED_STRING_HPP_
4
5#include <concepts>
6#include <cinttypes>
7#include <string>
8
10#include <libsbx/utility/target.hpp>
11
12#include <fmt/format.h>
13
14namespace sbx::utility {
15
16template<character Char, typename Hash = std::uint64_t, typename HashFunction = fnv1a_hash<Char, Hash>>
18
19public:
20
21 using char_type = HashFunction::char_type;
22 using size_type = HashFunction::size_type;
23 using hash_type = HashFunction::hash_type;
24
25 inline static constexpr auto npos = std::basic_string<char_type>::npos;
26
27 constexpr basic_hashed_string()
28 : _string{},
29 _hash{} {}
30
31 constexpr basic_hashed_string(const char_type* string, const size_type length)
32 : _string{string, length},
33 _hash{HashFunction{}(string)} {}
34
35 template<std::size_t Size>
36 constexpr basic_hashed_string(const char_type (&string)[Size])
37 : _string{string, Size - 1},
38 _hash{HashFunction{}(string)} {}
39
40 constexpr basic_hashed_string(const std::basic_string<char_type>& string)
41 : _string{string},
42 _hash{HashFunction{}(string)} {}
43
44 constexpr basic_hashed_string(const basic_hashed_string& other) = default;
45
46 constexpr basic_hashed_string(basic_hashed_string&& other) noexcept = default;
47
48 constexpr ~basic_hashed_string() = default;
49
50 constexpr auto operator=(const basic_hashed_string& other) -> basic_hashed_string& = default;
51
52 constexpr auto operator=(basic_hashed_string&& other) noexcept -> basic_hashed_string& = default;
53
54 template<typename Format, typename... Args>
55 static auto format(Format&& format, Args&&... args) -> basic_hashed_string {
56 return basic_hashed_string{fmt::format(std::forward<Format>(format), std::forward<Args>(args)...)};
57 }
58
59 constexpr auto operator==(const basic_hashed_string& other) const noexcept -> bool {
60 return _hash == other._hash;
61 }
62
63 constexpr auto data() const noexcept -> const char_type* {
64 return _string.data();
65 }
66
67 constexpr auto size() const noexcept -> size_type {
68 return _string.size();
69 }
70
71 constexpr auto hash() const noexcept -> hash_type {
72 return _hash;
73 }
74
75 constexpr auto c_str() const noexcept -> const char_type* {
76 return _string.c_str();
77 }
78
79 constexpr auto is_empty() const noexcept -> bool {
80 return _string.empty();
81 }
82
83 constexpr auto str() const noexcept -> const std::basic_string<char_type>& {
84 if constexpr (is_build_configuration_debug_v) {
85 return _string;
86 } else {
87 return _string.str();
88 }
89 }
90
91 constexpr auto rfind(std::basic_string_view<char_type> string) const noexcept -> size_type {
92 return _string.rfind(string);
93 }
94
95 constexpr auto substr(const size_type position = 0, const size_type count = npos) const -> std::basic_string<char_type> {
96 return _string.substr(position, count);
97 }
98
99 constexpr operator hash_type() const noexcept {
100 return _hash;
101 }
102
103private:
104
105 static constexpr auto _empty_cstr() noexcept -> const char_type* {
106 static constexpr auto null_char = char_type{0};
107 return &null_char;
108 }
109
110 struct empty_string {
111
112 template<typename... Args>
113 empty_string([[maybe_unused]] Args&&... args) {
114
115 }
116
117 constexpr auto data() const noexcept -> const char_type* {
118 return _empty_cstr();
119 }
120
121 constexpr auto size() const noexcept -> size_type {
122 return 0u;
123 }
124
125 constexpr auto c_str() const noexcept -> const char_type* {
126 return _empty_cstr();
127 }
128
129 constexpr auto empty() const noexcept -> bool {
130 return true;
131 }
132
133 constexpr auto str() const noexcept -> const std::basic_string<char_type>& {
134 static const auto empty = std::basic_string<char_type>{};
135
136 return empty;
137 }
138
139 constexpr auto rfind([[maybe_unused]] std::basic_string_view<char_type> string) const noexcept -> size_type {
140 return npos;
141 }
142
143
144 constexpr auto substr([[maybe_unused]] const size_type position, [[maybe_unused]] const size_type count) const -> std::basic_string<char_type> {
145 return {};
146 }
147
148 }; // struct empty_string
149
150 using string_type = std::conditional_t<is_build_configuration_debug_v, std::basic_string<char_type>, empty_string>;
151
152 [[no_unique_address]] string_type _string{};
153 hash_type _hash{};
154
155}; // class basic_hashed_string
156
157template<character Char, typename Hash = std::uint64_t, typename HashFunction = fnv1a_hash<Char, Hash>>
158constexpr auto operator==(const basic_hashed_string<Char, Hash, HashFunction>& lhs, const basic_hashed_string<Char, Hash, HashFunction>& rhs) noexcept -> bool {
159 return lhs.hash() == rhs.hash();
160}
161
162using hashed_string = basic_hashed_string<char>;
163
164using hashed_wstring = basic_hashed_string<wchar_t>;
165
166namespace literals {
167
168inline constexpr auto operator""_hs(const char* string, const std::size_t length) -> hashed_string {
169 return hashed_string{string, length};
170}
171
172inline constexpr auto operator""_hs(const wchar_t* string, const std::size_t length) -> hashed_wstring {
173 return hashed_wstring{string, length};
174}
175
176} // namespace literals
177
178} // namespace sbx::utility
179
180template<sbx::utility::character Char, typename Hash, typename HashFunction>
181struct fmt::formatter<sbx::utility::basic_hashed_string<Char, Hash, HashFunction>> {
182
183 template<typename ParseContext>
184 constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
185 return ctx.begin();
186 }
187
188 template<typename FormatContext>
189 auto format(const sbx::utility::basic_hashed_string<Char, Hash, HashFunction>& string, FormatContext& ctx) const -> decltype(ctx.out()) {
190 return fmt::format_to(ctx.out(), "{}", string.c_str());
191 }
192
193}; // struct fmt::formatter
194
195template<sbx::utility::character Char, typename Hash, typename HashFunction>
196struct std::hash<sbx::utility::basic_hashed_string<Char, Hash, HashFunction>> {
197 auto operator()(const sbx::utility::basic_hashed_string<Char, Hash, HashFunction>& string) const noexcept -> std::size_t {
198 return string.hash();
199 }
200}; // struct std::hash
201
202#endif // LIBSBX_UTILITY_HASHED_STRING_HPP_
Definition: hashed_string.hpp:17