libhatchet
Loading...
Searching...
No Matches
hxutility.h
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
8
9#include "libhatchet.h"
10
11#if HX_CPLUSPLUS
12extern "C" {
13
14// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
15#if HX_USE_MACROS_WITH_MODULE
16#error Header does not provide macros alone.
17#endif
18#endif
19
20// -- C Utilities --------------------------------------------------------------
21
25void hxfloat_dump(const float* address_, size_t floats_) hxattr_nonnull(1) hxattr_cold;
26
32void hxhex_dump(const void* address_, size_t bytes_, bool pretty_) hxattr_nonnull(1) hxattr_cold;
33
34#if HX_CPLUSPLUS
35} // extern "C"
36
37HX_NS_BEGIN_
38
39// -- C and C++ Utilities ------------------------------------------------------
40
43template<typename T_, hxsize_t N_> hxattr_nodiscard constexpr
44hxsize_t hxsize(T_ (&)[N_]) { return N_; }
45
46// -- C++ SFINAE ---------------------------------------------------------------
47// Substitution Failure Is Not An Error. enable_if checks.
48
50template<bool condition_, typename type_=void> struct hxenable_if_ { };
51template<typename type_> struct hxenable_if_<true, type_> { using type = type_; };
53
57template<bool condition_, typename type_=void>
58using hxenable_if_t = typename hxenable_if_<condition_, type_>::type;
60
65public:
67 template<typename T_> constexpr operator T_*() const { return 0; }
69 template<typename T_, typename M_> constexpr operator M_ T_::*() const { return 0; }
70private:
71 // No address-of operator.
72 void operator&(void) const = delete;
73};
74
80
83template<typename T_> struct hxremove_cv_ { using type = T_; };
84template<typename T_> struct hxremove_cv_<const T_> { using type = T_; };
85template<typename T_> struct hxremove_cv_<volatile T_> { using type = T_; };
86template<typename T_> struct hxremove_cv_<const volatile T_> { using type = T_; };
88
92template<typename T_> using hxremove_cv_t = typename hxremove_cv_<T_>::type;
93
95template<typename T_> struct hxremove_pointer_ { using type = T_; };
96template<typename T_> struct hxremove_pointer_<T_*> { using type = T_; };
97template<typename T_> struct hxremove_pointer_<T_* const> { using type = T_; };
98template<typename T_> struct hxremove_pointer_<T_* volatile> { using type = T_; };
99template<typename T_> struct hxremove_pointer_<T_* const volatile> { using type = T_; };
101
103template<typename T_> using hxremove_pointer_t = typename hxremove_pointer_<T_>::type;
104
106template<typename T_> struct hxremove_reference_ { using type = T_; };
107template<typename T_> struct hxremove_reference_<T_&> { using type = T_; };
108template<typename T_> struct hxremove_reference_<T_&&> { using type = T_; };
110
112template<typename T_> using hxremove_reference_t = typename hxremove_reference_<T_>::type;
113
116
119template<typename T_> T_&& hxdeclval(void) noexcept;
120
122struct hxtrue_t { constexpr static bool value = true; };
124struct hxfalse_t { constexpr static bool value = false; };
125
130template<typename T_, typename U_>
132private:
134 static hxtrue_t test_(T_&);
135 static hxfalse_t test_(T_&&);
136 static hxfalse_t test_(...);
138public:
139#if defined _MSC_VER
140#pragma warning(push)
141#pragma warning(disable: 4244 4267)
142#endif
143 constexpr static bool value = decltype(test_(hxdeclval<U_&>()))::value;
144#if defined _MSC_VER
145#pragma warning(pop)
146#endif
147};
148
150template<typename T_> struct hxis_array : public hxfalse_t { };
151template<typename T_, size_t size_> struct hxis_array<T_[size_]> : public hxtrue_t { };
152template<typename T_> struct hxis_array<T_[]> : public hxtrue_t { };
153
155template<typename T_> struct hxis_const : public hxfalse_t { };
156template<typename T_> struct hxis_const<const T_> : public hxtrue_t { };
157
159template<typename T_> struct hxis_floating_point_ : public hxfalse_t { };
160template<> struct hxis_floating_point_<float> : public hxtrue_t { };
161template<> struct hxis_floating_point_<double> : public hxtrue_t { };
162template<> struct hxis_floating_point_<long double> : public hxtrue_t { };
164
166template<typename T_>
167struct hxis_floating_point : public hxis_floating_point_<hxremove_cv_t<T_>> { };
168
170template<typename T_> struct hxis_integral_ : public hxfalse_t { };
171template<> struct hxis_integral_<bool> : public hxtrue_t { };
172template<> struct hxis_integral_<char> : public hxtrue_t { };
173template<> struct hxis_integral_<signed char> : public hxtrue_t { };
174template<> struct hxis_integral_<unsigned char> : public hxtrue_t { };
175template<> struct hxis_integral_<wchar_t> : public hxtrue_t { };
176template<> struct hxis_integral_<char16_t> : public hxtrue_t { };
177template<> struct hxis_integral_<char32_t> : public hxtrue_t { };
178#if HX_CPLUSPLUS >= 202002L
179template<> struct hxis_integral_<char8_t> : public hxtrue_t { };
180#endif
181template<> struct hxis_integral_<short> : public hxtrue_t { };
182template<> struct hxis_integral_<unsigned short> : public hxtrue_t { };
183template<> struct hxis_integral_<int> : public hxtrue_t { };
184template<> struct hxis_integral_<unsigned int> : public hxtrue_t { };
185template<> struct hxis_integral_<long> : public hxtrue_t { };
186template<> struct hxis_integral_<unsigned long> : public hxtrue_t { };
187template<> struct hxis_integral_<long long> : public hxtrue_t { };
188template<> struct hxis_integral_<unsigned long long> : public hxtrue_t { };
190
192template<typename T_>
193struct hxis_integral : public hxis_integral_<hxremove_cv_t<T_>> { };
194
196template<typename T_> struct hxis_lvalue_reference : public hxfalse_t { };
197template<typename T_> struct hxis_lvalue_reference<T_&> : public hxtrue_t { };
198
200template<typename T_> struct hxis_pointer_ : public hxfalse_t { };
201template<typename T_> struct hxis_pointer_<T_*> : public hxtrue_t { };
203
206template<typename T> struct hxis_pointer : hxis_pointer_<hxremove_cv_t<T>> { };
207
209template<typename T_> struct hxis_reference : public hxfalse_t { };
210template<typename T_> struct hxis_reference<T_&> : public hxtrue_t { };
211template<typename T_> struct hxis_reference<T_&&> : public hxtrue_t { };
212
214template<typename T_> struct hxis_rvalue_reference : public hxfalse_t { };
215template<typename T_> struct hxis_rvalue_reference<T_&&> : public hxtrue_t { };
216
218template<typename A_, typename B_> struct hxis_same : public hxfalse_t { };
219template<typename A_> struct hxis_same<A_, A_> : public hxtrue_t { };
220
222template<typename T_> struct hxis_void_ : public hxfalse_t { };
223template<> struct hxis_void_<void> : public hxtrue_t { };
225
227template<typename T_> struct hxis_void : public hxis_void_<hxremove_cv_t<T_>> { };
228
230template<typename T_> struct hxrestrict_t_ { using type = T_; };
231template<typename T_> struct hxrestrict_t_<T_*> { using type = T_* hxrestrict; };
232template<typename T_> struct hxrestrict_t_<T_* const> { using type = T_* const hxrestrict; };
234
237template<typename T_> using hxrestrict_t = typename hxrestrict_t_<T_>::type;
238
243hxattr_nodiscard constexpr bool hxisgraph(char ch_) {
244 return ((static_cast<unsigned char>(ch_) - 0x21u) < 0x5eu)
245 || ((static_cast<unsigned char>(ch_) & 0x80u) != 0u);
246}
247
254hxattr_nodiscard constexpr bool hxisspace(char ch_) {
255 return ch_ == ' ' || (static_cast<unsigned char>(ch_) - 0x09u) < 0x05u;
256}
257
264#if defined _MSC_VER
265 unsigned long index_ = 0ul;
266 ::_BitScanReverse(&index_, i_);
267 return static_cast<int>(index_);
268#elif defined __GNUC__ || defined __clang__
269 return 31 - __builtin_clz(i_);
270#else
271 float f_ = static_cast<float>(i_);
272 uint32_t bits_ = 0u; ::memcpy(&bits_, &f_, sizeof f_);
273 return static_cast<int>((bits_ >> 23) & 0xffu) - 127;
274#endif
275}
276
279template<typename T_>
280hxattr_nodiscard constexpr T_ hxabs(T_ x_) { return (x_ < T_()) ? (T_() - x_) : x_; }
281
287template<typename T_>
288hxattr_nodiscard constexpr T_ hxclamp(T_ x_, T_ minimum_, T_ maximum_) {
289#if HX_CPLUSPLUS >= 201402L
290 hxassertmsg(!(maximum_ < minimum_), "minimum <= maximum");
291#endif
292 return (x_ < minimum_) ? minimum_ : ((maximum_ < x_) ? maximum_ : x_);
293}
294
303template<typename T_>
305 static_assert(!hxis_lvalue_reference<T_>::value, "T must be a `T&&` reference");
306 return static_cast<T_&&>(x_);
307}
308
312template<typename T_>
314 return static_cast<T_&&>(x_);
315}
316
320template<typename T_>
321hxattr_nodiscard constexpr T_ hxmax(T_ x_, T_ y_) { return (y_ < x_) ? x_ : y_; }
322
326template<typename T_>
327hxattr_nodiscard constexpr T_ hxmin(T_ x_, T_ y_) { return (x_ < y_) ? x_ : y_; }
328
332template<typename T_>
333constexpr hxremove_reference_t<T_>&& hxmove(T_&& t_) {
334 return static_cast<hxremove_reference_t<T_>&&>(t_);
335}
336
339template<typename T_>
340hxconstexpr void hxswap(T_& x_, T_& y_) {
341 // Provides an optimization hint.
342 hxassertmsg(&x_ != &y_, "hxswap No swapping with self");
343 T_ t_(hxmove(x_));
344 x_ = hxmove(y_);
345 y_ = hxmove(t_);
346}
347
353template<typename T_>
354void hxswap_memcpy(T_& x_, T_& y_) {
355 hxassertmsg(&x_ != &y_, "hxswap_memcpy No swapping with self");
356 char t_[sizeof x_];
357 ::memcpy(t_, &y_, sizeof x_); // NOLINT(bugprone-undefined-memory-manipulation)
358 ::memcpy(static_cast<void*>(&y_), &x_, sizeof x_); // NOLINT(bugprone-undefined-memory-manipulation)
359 ::memcpy(static_cast<void*>(&x_), t_, sizeof x_); // NOLINT(bugprone-undefined-memory-manipulation)
360}
361
362HX_NS_END_
363#else // !HX_CPLUSPLUS
364
365// -- C Macro Utility API - Does it all backwards in heels --------------------
366
369#define hxsize(x_) (sizeof(x_) / sizeof(x_)[0])
370
374#define hxabs(x_) ((x_) < 0 ? (0 - (x_)) : (x_))
375
381#define hxclamp(x_, minimum_, maximum_) \
382 ((x_) < (minimum_) ? (minimum_) : ((maximum_) < (x_) ? (maximum_) : (x_)))
383
388#define hxmax(x_, y_) ((y_) < (x_) ? (x_) : (y_))
389
394#define hxmin(x_, y_) ((x_) < (y_) ? (x_) : (y_))
395
401#define hxswap_memcpy(x_,y_) do { \
402 char t_[sizeof(x_) == sizeof(y_) ? (int)sizeof(x_) : -1]; \
403 memcpy(t_, &(y_), sizeof(x_)); \
404 memcpy(&(y_), &(x_), sizeof(x_)); \
405 memcpy(&(x_), t_, sizeof(x_)); } while(0)
406
407#endif // !HX_CPLUSPLUS
hxnullptr_t - A class that will only convert to a null T pointer.
Definition hxutility.h:64
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:120
#define hxrestrict
hxrestrict - A pointer attribute indicating that for the lifetime of that pointer,...
Definition hxsettings.h:67
#define hxinline_constexpr
hxinline_constexpr - Enables C++17 compatable "inline constexpr" usage for variables so they can be e...
Definition hxsettings.h:272
#define hxattr_nonnull(...)
hxattr_nonnull - Indicates that a function has args that should not be null.
Definition hxsettings.h:97
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:89
#define hxattr_cold
hxattr_cold - Optimize a function for size.
Definition hxsettings.h:78
#define hxconstexpr
hxconstexpr - Enables C++23 compatable constexpr usage for functions as that has support for destruct...
Definition hxsettings.h:263
constexpr bool hxisgraph(char ch_)
hxisgraph - Implements standard isgraph for a locale where all non-ASCII characters are considered gr...
Definition hxutility.h:243
typename hxremove_cv_< T >::type hxremove_cv_t
Internal.
Definition hxutility.h:92
typename hxrestrict_t_< T >::type hxrestrict_t
hxrestrict_t - Adds the __restrict keyword to C++ pointers.
Definition hxutility.h:237
constexpr void hxswap(T &x_, T &y_)
hxswap - Exchanges the contents of x and y using a temporary.
Definition hxutility.h:340
constexpr T && hxforward(hxremove_reference_t< T > &&x_)
hxforward - Implements std::forward.
Definition hxutility.h:304
void hxhex_dump(const void *address_, size_t bytes_, bool pretty_)
hxhex_dump - Prints an array of bytes formatted in hexadecimal.
constexpr T hxabs(T x_)
hxabs - Returns the absolute value of x using a < comparison.
Definition hxutility.h:280
void hxswap_memcpy(T &x_, T &y_)
hxswap_memcpy - Exchanges the contents of x and y using memcpy and a stack temporary.
Definition hxutility.h:354
hxremove_cv_t< hxremove_reference_t< T > > hxremove_cvref_t
hxremove_cvref_t<T> - Returns T with const, volatile, and references removed.
Definition hxutility.h:115
constexpr hxnullptr_t hxnullptr
hxnullptr - An instance of a class that will only convert to a null pointer.
Definition hxutility.h:79
constexpr T hxclamp(T x_, T minimum_, T maximum_)
hxclamp - Returns x clamped between the minimum and maximum using < comparisons.
Definition hxutility.h:288
constexpr T hxmax(T x_, T y_)
hxmax - Returns the maximum value of x and y using a < comparison.
Definition hxutility.h:321
HX_NS_BEGIN_ constexpr hxsize_t hxsize(T(&)[N_])
hxsize - Returns the size of a C array.
Definition hxutility.h:44
T && hxdeclval(void) noexcept
hxdeclval - Implements std::declval.
constexpr T hxmin(T x_, T y_)
hxmin - Returns the minimum value of x and y using a < comparison.
Definition hxutility.h:327
void hxfloat_dump(const float *address_, size_t floats_)
hxfloat_dump - Prints an array of floating point values.
constexpr bool hxisspace(char ch_)
hxisspace - Implements standard isspace for a locale where all non-ASCII characters are considered gr...
Definition hxutility.h:254
constexpr hxremove_reference_t< T > && hxmove(T &&t_)
hxmove - Implements std::move.
Definition hxutility.h:333
typename hxremove_reference_< T >::type hxremove_reference_t
hxremove_reference_t<T> - Returns T with references removed.
Definition hxutility.h:112
typename hxremove_pointer_< T >::type hxremove_pointer_t
hxremove_pointer_t<T> - Returns T with one pointer level removed.
Definition hxutility.h:103
int hxlog2i(uint32_t i_)
hxlog2i - Returns log2(n) as an integer which is the power of 2 of the largest bit in n.
Definition hxutility.h:263
Provides core macros, memory management and feature detection.
#define hxassertmsg(x_,...)
hxassertmsg(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:101
ptrdiff_t hxsize_t
hxsize_t - A signed size type, same as ssize_t or ptrdiff_t.
Definition libhatchet.h:209
hxbinds_directly<T, U> - Provides a value constant that is true when an lvalue of type U binds to T& ...
Definition hxutility.h:131
static constexpr bool value
Definition hxutility.h:143
hxfalse_t - Implements std::false_type.
Definition hxutility.h:124
static constexpr bool value
Definition hxutility.h:124
hxis_array - Implements std::is_array.
Definition hxutility.h:150
hxis_const - Implements std::is_const.
Definition hxutility.h:155
hxis_floating_point - Implements std::is_floating_point.
Definition hxutility.h:167
hxis_integral - Implements std::is_integral.
Definition hxutility.h:193
hxis_lvalue_reference - Implements std::is_lvalue_reference.
Definition hxutility.h:196
hxis_pointer - Returns whether T is a pointer type as hxis_pointer<T>::value.
Definition hxutility.h:206
hxis_reference - Implements std::is_reference.
Definition hxutility.h:209
hxis_rvalue_reference - Implements std::is_rvalue_reference.
Definition hxutility.h:214
hxis_same - Implements std::is_same.
Definition hxutility.h:218
hxis_void - Implements std::is_void.
Definition hxutility.h:227
hxtrue_t - Implements std::true_type.
Definition hxutility.h:122
static constexpr bool value
Definition hxutility.h:122