2#ifndef LIBSBX_UTILITY_HASHED_STRING_HPP_
3#define LIBSBX_UTILITY_HASHED_STRING_HPP_
10#include <libsbx/utility/target.hpp>
12#include <fmt/format.h>
14namespace sbx::utility {
16template<
character Char,
typename Hash = std::u
int64_t,
typename HashFunction = fnv1a_hash<Char, Hash>>
21 using char_type = HashFunction::char_type;
22 using size_type = HashFunction::size_type;
23 using hash_type = HashFunction::hash_type;
25 inline static constexpr auto npos = std::basic_string<char_type>::npos;
32 : _string{string, length},
33 _hash{HashFunction{}(string)} {}
35 template<std::
size_t Size>
37 : _string{string, Size - 1},
38 _hash{HashFunction{}(string)} {}
42 _hash{HashFunction{}(string)} {}
54 template<
typename Format,
typename... Args>
56 return basic_hashed_string{fmt::format(std::forward<Format>(format), std::forward<Args>(args)...)};
60 return _hash == other._hash;
63 constexpr auto data()
const noexcept ->
const char_type* {
64 return _string.data();
67 constexpr auto size()
const noexcept -> size_type {
68 return _string.size();
71 constexpr auto hash()
const noexcept -> hash_type {
75 constexpr auto c_str()
const noexcept ->
const char_type* {
76 return _string.c_str();
79 constexpr auto is_empty()
const noexcept ->
bool {
80 return _string.empty();
83 constexpr auto str()
const noexcept ->
const std::basic_string<char_type>& {
84 if constexpr (is_build_configuration_debug_v) {
91 constexpr auto rfind(std::basic_string_view<char_type>
string)
const noexcept -> size_type {
92 return _string.rfind(
string);
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);
99 constexpr operator hash_type()
const noexcept {
105 static constexpr auto _empty_cstr()
noexcept ->
const char_type* {
106 static constexpr auto null_char = char_type{0};
110 struct empty_string {
112 template<
typename... Args>
113 empty_string([[maybe_unused]] Args&&... args) {
117 constexpr auto data()
const noexcept ->
const char_type* {
118 return _empty_cstr();
121 constexpr auto size()
const noexcept -> size_type {
125 constexpr auto c_str()
const noexcept ->
const char_type* {
126 return _empty_cstr();
129 constexpr auto empty()
const noexcept ->
bool {
133 constexpr auto str()
const noexcept ->
const std::basic_string<char_type>& {
134 static const auto empty = std::basic_string<char_type>{};
139 constexpr auto rfind([[maybe_unused]] std::basic_string_view<char_type>
string)
const noexcept -> size_type {
144 constexpr auto substr([[maybe_unused]]
const size_type position, [[maybe_unused]]
const size_type count)
const -> std::basic_string<char_type> {
150 using string_type = std::conditional_t<is_build_configuration_debug_v, std::basic_string<char_type>, empty_string>;
152 [[no_unique_address]] string_type _string{};
157template<
character Char,
typename Hash = std::u
int64_t,
typename HashFunction = fnv1a_hash<Char, Hash>>
159 return lhs.hash() == rhs.hash();
162using hashed_string = basic_hashed_string<char>;
164using hashed_wstring = basic_hashed_string<wchar_t>;
168inline constexpr auto operator""_hs(
const char*
string,
const std::size_t length) -> hashed_string {
169 return hashed_string{string, length};
172inline constexpr auto operator""_hs(
const wchar_t*
string,
const std::size_t length) -> hashed_wstring {
173 return hashed_wstring{string, length};
180template<sbx::utility::
character Char,
typename Hash,
typename HashFunction>
181struct fmt::formatter<sbx::utility::basic_hashed_string<Char, Hash, HashFunction>> {
183 template<
typename ParseContext>
184 constexpr auto parse(ParseContext& ctx) ->
decltype(ctx.begin()) {
188 template<
typename FormatContext>
190 return fmt::format_to(ctx.out(),
"{}",
string.c_str());
195template<sbx::utility::
character Char,
typename Hash,
typename HashFunction>
196struct std::hash<sbx::utility::basic_hashed_string<Char, Hash, HashFunction>> {
198 return string.hash();
Definition: hashed_string.hpp:17