nngn
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1#ifndef NNGN_UTILS_UTILS_H
2#define NNGN_UTILS_UTILS_H
3
4#include <bit>
5#include <cassert>
6#include <cstring>
7#include <functional>
8#include <span>
9#include <string>
10#include <string_view>
11#include <type_traits>
12#include <utility>
13#include <vector>
14
15#include "concepts.h"
17
18#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
19
20#define NNGN_DEFAULT_CONSTRUCT(x) \
21 x() = default; \
22 x(const x&) = default; \
23 x &operator=(const x&) = default; \
24 x(x&&) noexcept = default; \
25 x &operator=(x&&) noexcept = default; \
26
27#define NNGN_VIRTUAL(x) \
28 NNGN_DEFAULT_CONSTRUCT(x) \
29 virtual ~x() = default;
30
31#define NNGN_PURE_VIRTUAL(x) \
32 NNGN_DEFAULT_CONSTRUCT(x) \
33 virtual ~x() = 0;
34
35#define NNGN_NO_COPY(x) \
36 x(const x&) = delete; \
37 x &operator=(const x&) = delete;
38
39#define NNGN_MOVE_ONLY(x) \
40 NNGN_NO_COPY(x) \
41 x(x&&) noexcept = default; \
42 x &operator=(x&&) noexcept = default;
43
44#define NNGN_NO_MOVE(x) \
45 x(const x&) = delete; \
46 x &operator=(const x&) = delete; \
47 x(x&&) noexcept = delete; \
48 x &operator=(x&&) noexcept = delete;
49
50#define NNGN_ANON_IMPL1(l) nngn_anon_ ## l
51#define NNGN_ANON_IMPL0(l) NNGN_ANON_IMPL1(l)
52#define NNGN_ANON() NNGN_ANON_IMPL0(__LINE__)
53#define NNGN_ANON_DECL(...) \
54 [[maybe_unused]] const auto NNGN_ANON() = __VA_ARGS__;
55
56#define NNGN_CONTAINER_OF(t, n, p) \
57 (nngn::byte_cast<t*>(nngn::byte_cast<char*>(p) - offsetof(t, n)))
58
59#define NNGN_BIND_MEM_FN(x, f) \
60 std::bind_front([] { \
61 constexpr auto nngn_ret = \
62 &std::remove_pointer_t<std::decay_t<decltype(x)>>::f; \
63 static_assert(std::is_member_function_pointer_v<decltype(nngn_ret)>); \
64 return nngn_ret; \
65 }(), (x))
66
67#define NNGN_EXPOSE_ITERATOR(n, m) \
68 NNGN_EXPOSE_ITERATOR0(n, m, cbegin) \
69 NNGN_EXPOSE_ITERATOR0(n, m, cend) \
70 NNGN_EXPOSE_ITERATOR0(n, m, begin) \
71 NNGN_EXPOSE_ITERATOR0(n, m, end)
72#define NNGN_EXPOSE_ITERATOR0(n, m, i) \
73 auto n##i(void) const { using std::i; return i(this->m); } \
74 auto n##i(void) { using std::i; return i(this->m); }
75
76namespace nngn {
77
78namespace detail {
79
80template<typename T>
81struct chain_cast {
82 constexpr decltype(auto) operator<<(auto &&x) {
83 return static_cast<T>(FWD(x));
84 }
85};
86
87}
88
89enum class empty {};
90
91template<typename T> struct always_false : std::false_type {};
92
94template<typename ...Ts>
95constexpr decltype(auto) chain_cast(auto &&x) {
96 return (detail::chain_cast<Ts>{} << ... << FWD(x));
97}
98
100template<typename To, typename From>
101To narrow(const From &x) {
102 To ret = static_cast<To>(x);
103 assert(static_cast<From>(ret) == x);
104 return ret;
105}
106
108template<typename T, typename U>
109constexpr decltype(auto) cast(U &&x) {
110 if constexpr(requires { const_cast<T>(FWD(x)); })
111 return const_cast<T>(FWD(x));
112 else if constexpr(requires { static_cast<T>(FWD(x)); })
113 return static_cast<T>(FWD(x));
114 else
115 return reinterpret_cast<T>(FWD(x));
116}
117
119template<typename To, typename From>
120requires byte_pointer<To> || byte_pointer<From>
121constexpr To byte_cast(From p) {
122 constexpr bool is_const = std::is_const_v<std::remove_pointer_t<From>>;
123 using V = std::conditional_t<is_const, const void*, void*>;
124 return chain_cast<To, V>(p);
125}
126
128template<typename To, typename From>
129requires
130 byte_type<To> || char_type<To>
131 || byte_type<From> || char_type<From>
132std::span<To> byte_cast(std::span<From> s) {
133 assert(!(s.size() % sizeof(To)));
134 return {byte_cast<To*>(s.data()), s.size() / sizeof(To)};
135}
136
137template<enum_ T>
138inline constexpr auto to_underlying(T t) {
139 return static_cast<std::underlying_type_t<T>>(t);
140}
141
143inline constexpr auto ptr_diff(const auto *lhs, const auto *rhs) {
145}
146
148inline constexpr bool ptr_cmp(const auto *p0, const auto *p1)
149 { return static_cast<const void*>(p0) == static_cast<const void*>(p1); }
150
152template<standard_layout T>
153std::size_t offsetof_ptr(auto T::*p) {
154 T t = {};
155 return static_cast<std::size_t>(ptr_diff(&(t.*p), &t));
156}
157
158inline auto as_bytes(const void *p) { return static_cast<const std::byte*>(p); }
159inline auto as_bytes(void *p) { return static_cast<std::byte*>(p); }
160
161inline std::span<const std::byte> as_byte_span(const auto *x)
162 { return {as_bytes(x), sizeof(*x)}; }
163inline std::span<std::byte> as_byte_span(auto *x)
164 { return {as_bytes(x), sizeof(*x)}; }
165
166inline constexpr bool str_less(const char *lhs, const char *rhs) {
167 if(!std::is_constant_evaluated())
168 return std::strcmp(lhs, rhs) < 0;
169 while(*lhs && *rhs && *lhs == *rhs)
170 ++lhs, ++rhs;
171 return *rhs && (!*lhs || *lhs < *rhs);
172}
173
174template<typename To, typename From>
175requires (
176 sizeof(To) == sizeof(From)
177 && std::is_trivially_copyable_v<To>
178 && std::is_trivially_copyable_v<From>)
179constexpr auto bit_cast(const From &from) {
180 static_assert(std::is_trivially_constructible_v<To>);
181 To ret = {};
182 std::memcpy(&ret, &from, sizeof(To));
183 return ret;
184}
185
186template<typename T>
187constexpr auto set_bit(T t, T mask, bool value) {
188 assert(std::popcount(mask) == 1);
189 return t ^ ((t ^ -T{value}) & mask);
190}
191
197template<typename> struct member_obj_type;
198
199template<typename T, typename O>
200struct member_obj_type<O(T::*)> : std::type_identity<T> {};
201
202template<typename T, typename R, typename ...Args>
203struct member_obj_type<R(T::*)(Args...)> : std::type_identity<T> {};
204
206template<typename T>
208
209template<member_pointer auto p>
210struct mem_obj {
211 template<typename T>
212 requires requires (T t) { {t.*p}; }
213 constexpr decltype(auto) operator()(const T &t)
214 { return t.*p; }
215};
216
217template<member_pointer auto p>
219 template<typename T>
220 requires requires (T t) { {t.*p}; }
221 constexpr bool operator()(const T &lhs, const T &rhs)
222 { return lhs.*p < rhs.*p; }
223};
224
229constexpr decltype(auto) rptr(auto &&r) { return &r; }
230
231bool read_file(std::string_view filename, std::string *ret);
232bool read_file(std::string_view filename, std::vector<std::byte> *ret);
233
234}
235
236#endif
assert
Definition debug.lua:3
#define T(f0, f1, f2)
local r
Definition gamma.lua:7
Definition audio.cpp:7
constexpr auto bit_cast(const From &from)
Definition utils.h:179
constexpr To byte_cast(From p)
reinterpret_cast restricted to conversions from/to char/uchar.
Definition utils.h:121
bool read_file(std::string_view filename, std::string *ret)
Definition utils.cpp:30
constexpr auto to_underlying(T t)
Definition utils.h:138
constexpr chain_cast(auto &&x)
Performs successive static_casts, right to left.
Definition utils.h:95
constexpr rptr(auto &&r)
Allows passing an rvalue pointer to a function.
Definition utils.h:229
constexpr auto set_bit(T t, T mask, bool value)
Definition utils.h:187
constexpr bool str_less(const char *lhs, const char *rhs)
Definition utils.h:166
constexpr cast(U &&x)
Cast value to T with the strictest cast operator.
Definition utils.h:109
constexpr bool ptr_cmp(const auto *p0, const auto *p1)
Compares the address of two pointers.
Definition utils.h:148
To narrow(const From &x)
Casts x to a narrower type, asserting that the value is preserved.
Definition utils.h:101
std::size_t offsetof_ptr(auto T::*p)
Similar to the stdlib's offsetof, but using member data pointers.
Definition utils.h:153
std::span< const std::byte > as_byte_span(const auto *x)
Definition utils.h:161
empty
Definition utils.h:89
constexpr auto ptr_diff(const auto *lhs, const auto *rhs)
Signed distance in bytes between pointers.
Definition utils.h:143
auto as_bytes(const void *p)
Definition utils.h:158
typename member_obj_type< T >::type member_obj_type_t
Definition utils.h:207
#define FWD(...)
Definition utils.h:18
Definition utils.h:91
Definition utils.h:81
Definition utils.h:210
Definition utils.h:218
constexpr bool operator()(const T &lhs, const T &rhs)
Definition utils.h:221
Type associated with a member object/function pointer.
Definition utils.h:197
std::chrono::seconds s
Definition timing.cpp:6