libhatchet
Loading...
Searching...
No Matches
hxkey.hpp
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: © 2017-2026 Adrian Johnston.
3// SPDX-License-Identifier: MIT
4// This file is licensed under the MIT license found in the LICENSE.md file.
5
14
15#include "libhatchet.h"
16
17// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
18#if HX_USE_MACROS_WITH_MODULE
19#error Header does not provide macros alone.
20#endif
21
22#include "hxutility.h"
23
24HX_NS_BEGIN_
25
27// UTF-8 string detection. Does not match signed/unsigned char.
28template<typename T_> struct hxis_string_ : public hxfalse_t { };
29template<> struct hxis_string_<char*> : public hxtrue_t { };
30template<> struct hxis_string_<const char*> : public hxtrue_t { };
31template<> struct hxis_string_<volatile char*> : public hxtrue_t { };
32template<> struct hxis_string_<const volatile char*> : public hxtrue_t { };
33template<size_t size_> struct hxis_string_<char[size_]> : public hxtrue_t { };
34template<size_t size_> struct hxis_string_<const char[size_]> : public hxtrue_t { };
35template<size_t size_> struct hxis_string_<volatile char[size_]> : public hxtrue_t { };
36template<size_t size_> struct hxis_string_<const volatile char[size_]> : public hxtrue_t { };
37template<> struct hxis_string_<char[]> : public hxtrue_t { };
38template<> struct hxis_string_<const char[]> : public hxtrue_t { };
39template<> struct hxis_string_<volatile char[]> : public hxtrue_t { };
40template<> struct hxis_string_<const volatile char[]> : public hxtrue_t { };
42
46template<typename T_>
48bool hxis_string(void) {
49 return hxis_string_<hxremove_cvref_t<T_>>::value;
50}
51
56template<typename T_=void, typename enabled_t=void>
58public:
59 template<typename A_, typename B_>
61 bool operator()(const A_& a_, const B_& b_) const { return a_ == b_; }
62};
63
66template<typename T_>
67class hxkey_equal_t<T_, hxenable_if_t<hxis_string<T_>()>> {
68public:
69 hxattr_nodiscard hxinline bool operator()(const volatile char* a_, const volatile char* b_) const {
70 return ::strcmp(const_cast<const char*>(a_), const_cast<const char*>(b_)) == 0;
71 }
72};
73
78template<typename A_, typename B_>
80bool hxkey_equal(const A_& a_, const B_& b_) {
81 return hxkey_equal_t<A_>{}(a_, b_);
82}
83
90template<typename T_=void, typename enabled_t=void>
92public:
93 template<typename A_, typename B_>
95 bool operator()(const A_& a_, const B_& b_) const { return a_ < b_; }
96};
97
101template<typename T_>
102class hxkey_less_t<T_, hxenable_if_t<hxis_string<T_>()>> {
103public:
104 hxattr_nodiscard hxinline bool operator()(const volatile char* a_, const volatile char* b_) const {
105 return ::strcmp(const_cast<const char*>(a_), const_cast<const char*>(b_)) < 0;
106 }
107};
108
113template<typename A_, typename B_>
115bool hxkey_less(const A_& a_, const B_& b_) {
116 return hxkey_less_t<A_>{}(a_, b_);
117}
118
120// xxhash32 prime constants and avalanche mixing. Useful when hashing sequential
121// data. These are used by hxkey_hash_t specializations below.
122hxinline_constexpr hxhash_t hxhash_prime1_ = hxhash_t{0x9E3779B1u};
123hxinline_constexpr hxhash_t hxhash_prime2_ = hxhash_t{0x85EBCA77u};
124hxinline_constexpr hxhash_t hxhash_prime3_ = hxhash_t{0xC2B2AE3Du};
125hxinline_constexpr hxhash_t hxhash_prime4_ = hxhash_t{0x27D4EB2Fu};
126hxinline_constexpr hxhash_t hxhash_prime5_ = hxhash_t{0x165667B1u};
127
128// xxhash32 avalanche: x ^= x >> 15, x *= prime2, x ^= x >> 13, x *= prime3, x ^= x >> 16.
130hxhash_t hxhash_avalanche_(hxhash_t x_) {
131 x_ ^= x_ >> 15u;
132 x_ *= hxhash_prime2_;
133 x_ ^= x_ >> 13u;
134 x_ *= hxhash_prime3_;
135 x_ ^= x_ >> 16u;
136 return x_;
137}
139
145template<typename T_, typename enabled_t=void>
147public:
149 // xxhash32 short-input path: seed=0, length=4, single 4-byte word.
150 hxhash_t h_ = hxhash_prime5_ + hxhash_t{4u};
151 // Did you write a custom hxkey_hash_t specialization?
152 h_ += static_cast<hxhash_t>(x_) * hxhash_prime3_;
153 h_ = ((h_ << 17u) | (h_ >> 15u)) * hxhash_prime4_;
154 return hxhash_avalanche_(h_);
155 }
156};
157
161template<typename T_>
162class hxkey_hash_t<T_, hxenable_if_t<hxis_string<T_>()>> {
163public:
164 hxattr_nodiscard hxinline hxhash_t operator()(const volatile char* s_) const {
165 const char* t_ = const_cast<const char*>(s_);
166 hxhash_t h_ = hxhash_prime5_;
167 while(*t_ != '\0') {
168 h_ += static_cast<hxhash_t>(static_cast<unsigned char>(*t_++)) * hxhash_prime5_;
169 h_ = ((h_ << 11u) | (h_ >> 21u)) * hxhash_prime1_;
170 }
171 return hxhash_avalanche_(h_);
172 }
173};
174
178template<typename T_>
182
183HX_NS_END_
bool operator()(const volatile char *a_, const volatile char *b_) const
Definition hxkey.hpp:69
hxkey_equal_t<T> - A constexpr callable that returns true if two objects are equivalent.
Definition hxkey.hpp:57
constexpr bool operator()(const A_ &a_, const B_ &b_) const
Definition hxkey.hpp:61
hxhash_t operator()(const volatile char *s_) const
Definition hxkey.hpp:164
hxkey_hash_t<T> - A callable that returns the xxhash32 of a numeric value cast to 32 bits.
Definition hxkey.hpp:146
hxhash_t operator()(const T &x_) const
Definition hxkey.hpp:148
bool operator()(const volatile char *a_, const volatile char *b_) const
Definition hxkey.hpp:104
hxkey_less_t<T> - A constexpr callable that returns true if the first object is less than the second.
Definition hxkey.hpp:91
constexpr bool operator()(const A_ &a_, const B_ &b_) const
Definition hxkey.hpp:95
constexpr bool hxkey_equal(const A_ &a_, const B_ &b_)
hxkey_equal - Returns true if a and b are equivalent, deducing A and invoking hxkey_equal_t<A>.
Definition hxkey.hpp:80
hxhash_t hxkey_hash(const T &x_)
hxkey_hash - Returns the hash of x, deducing T and invoking hxkey_hash_t<T>.
Definition hxkey.hpp:179
HX_NS_BEGIN_ constexpr bool hxis_string(void)
hxis_string<T> - Checks if T is some kind of char* or char array, ignoring any top level const,...
Definition hxkey.hpp:48
constexpr bool hxkey_less(const A_ &a_, const B_ &b_)
hxkey_less - Returns true if a is less than b, deducing A and invoking hxkey_less_t<A>.
Definition hxkey.hpp:115
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:125
#define hxinline_constexpr
hxinline_constexpr - Enables C++17 compatable "inline constexpr" usage for variables so they can be e...
Definition hxsettings.h:275
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:98
#define hxattr_flatten
hxattr_flatten - Inline every call inside a function's body into it, recursively, regardless of the c...
Definition hxsettings.h:90
#define hxconstexpr
hxconstexpr - Enables C++23 compatable constexpr usage for functions as that has support for destruct...
Definition hxsettings.h:266
A few utility functions and most standard C++ meta programming functions.
Provides core macros, memory management and feature detection.
uint32_t hxhash_t
hxhash_t - Unsigned 32-bit hash value. Expect collisions.
Definition libhatchet.h:210
hxfalse_t - Implements std::false_type.
Definition hxutility.h:112
hxtrue_t - Implements std::true_type.
Definition hxutility.h:110