DynXX-Cxx
Loading...
Searching...
No Matches
Types.hxx
Go to the documentation of this file.
1#pragma once
2
3#include "../C/Types.h"
4
5#include <cstdint>
6#include <cstring>
7#include <string_view>
8#include <string>
9#include <optional>
10#include <span>
11#include <vector>
12#include <variant>
13#include <unordered_map>
14#include <functional>
15#include <limits>
16#include <type_traits>
17
18// Assertions
19
20#define AssertMove(T) \
21 static_assert(std::is_move_constructible_v<T>, #T " MUST BE MOVE CONSTRUCTIBLE!"); \
22 static_assert(std::is_move_assignable_v<T>, #T " MUST BE MOVE ASSIGNABLE!"); \
23 static_assert(std::is_nothrow_move_constructible_v<T>, #T " MUST BE NOTHROW MOVE CONSTRUCTIBLE!"); \
24 static_assert(std::is_nothrow_move_assignable_v<T>, #T " MUST BE NOTHROW MOVE ASSIGNABLE!")
25
26// Concepts
27
28template<typename T>
29concept ConstT = std::is_const_v<T>;
30
31template<typename T>
32concept VoidT = std::is_void_v<T>;
33
34template<typename T>
35concept NumberT =
36 std::is_arithmetic_v<T> ||
37 (std::is_enum_v<T> && std::is_convertible_v<std::underlying_type_t<T>, int>);
38
39template<typename T>
40concept IntegerT = NumberT<T> && std::integral<T>;
41
42template<typename T>
43concept FloatT = NumberT<T> && std::floating_point<T>;
44
45template<typename T>
46concept EnumT = NumberT<T> && std::is_enum_v<T>;
47
48template<typename T>
49concept CharacterT =
50 std::is_same_v<T, char> || std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>
51#if defined(__cpp_char8_t)
52 || std::is_same_v<T, char8_t>
53#endif
54 || std::is_same_v<T, char16_t> || std::is_same_v<T, char32_t> || std::is_same_v<T, wchar_t>;
55
56template<typename T>
57concept CStringT = std::is_same_v<T, const char*> || std::is_same_v<T, char*>;
58
59template<EnumT E>
60constexpr auto underlying(E e) noexcept -> std::underlying_type_t<E>
61{
62 return static_cast<std::underlying_type_t<E>>(e);
63}
64
65template<typename T>
66concept KeyT = std::convertible_to<T, std::string_view> ||
67 std::convertible_to<T, std::string> ||
68 std::convertible_to<T, const char*>;
69
70template<class T, class U>
71concept DerivedT = std::is_base_of_v<U, T>;
72
73template<typename To, typename From>
75 std::is_polymorphic_v<From> && std::is_polymorphic_v<To> &&
76 (std::is_base_of_v<To, From> || std::is_base_of_v<From, To> || requires(From* f) {
77 dynamic_cast<To*>(f);
78 });
79
80template<typename T>
81concept MemcpyableT = std::is_trivially_copyable_v<T>;
82
83template<typename T>
84concept HashableT = requires(T a)
85{
86 { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
87};
88
89template<typename T>
90concept CompletelyComparableT = requires(T a, T b)
91{
92 { a <=> b } -> std::convertible_to<std::partial_ordering>;
93};
94
95template<typename T>
96concept EqualityComparableT = requires(T a, T b)
97{
98 { a == b } -> std::convertible_to<bool>;
99 { a != b } -> std::convertible_to<bool>;
100};
101
102template<typename T>
103concept IterableT = requires(T a)
104{
105 { std::begin(a) } -> std::input_iterator;
106 { std::end(a) } -> std::sentinel_for<decltype(std::begin(a))>;
107};
108
109template<typename R>
110concept InRangeT =
111 std::ranges::input_range<R> &&
112 requires(R& r) {
113 { r.size() } -> std::integral;
114 };
115
116template<typename R>
117concept OutRangeT =
118 std::ranges::range<R> &&
119 requires(R& r, std::size_t n) {
120 r.resize(n);
121 };
122
123template<typename F>
124concept RunnableT = requires(F&& f) {
125 { std::invoke(std::forward<F>(f)) } -> std::same_as<void>;
126};
127
128// Utils using concept
129
130template<typename To, typename From>
132To* dynamicCastX(From* ptr) noexcept {
133 return dynamic_cast<To*>(ptr);
134}
135
136template<HashableT T>
137std::size_t getHash(const T &value) {
138 return std::hash<T>{}(value);
139}
140
141template<IterableT T>
142void iterate(const T &container, std::function<void(const typename T::value_type &)> &&func) {
143 for (const auto &e: container) {
144 std::move(func)(e);
145 }
146}
147
148// Limits constants
149
150template<NumberT T>
151constexpr T MinV() {
152 return (std::numeric_limits<T>::min)();
153}
154
155template<NumberT T>
156constexpr T MaxV() {
157 return (std::numeric_limits<T>::max)();
158}
159
160constexpr auto MinInt32 = MinV<int32_t>();
161constexpr auto MaxInt32 = MaxV<int32_t>();
162constexpr auto MinInt64 = MinV<int64_t>();
163constexpr auto MaxInt64 = MaxV<int64_t>();
164constexpr auto MinFloat32 = MinV<float>();
165constexpr auto MaxFloat32 = MaxV<float>();
166constexpr auto MinFloat64 = MinV<double>();
167constexpr auto MaxFloat64 = MaxV<double>();
170
171// String to Number
172
174
176
177float str2float32(const std::string &str, float defaultF = MinFloat32);
178
179double str2float64(const std::string &str, double defaultF = MinFloat64);
180
181long double str2float128(const std::string &str, long double defaultF = MinFloat128);
182
183// Any Type
184
185using Num = std::variant<int64_t, double>;
186using Any = std::variant<int64_t, double, std::string>;
187
188inline auto Any2String(const Any &v) {
189 return std::visit([](const auto &x) {
190 if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::string>) {
191 return x;
192 } else {
193 return std::to_string(x);
194 }
195 }, v);
196}
197
198inline auto Any2Integer(const Any &a, int64_t defaultI = MinInt64) {
199 return std::visit([defaultI](const auto &x) {
200 if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::string>) {
201 return str2int64(x, defaultI);
202 } else {
203 return static_cast<int64_t>(x);
204 }
205 }, a);
206}
207
208inline auto Any2Float(const Any &a, double defaultF = MinFloat64) {
209 return std::visit([defaultF](const auto &x) {
210 if constexpr (std::is_same_v<std::decay_t<decltype(x)>, std::string>) {
211 return str2float64(x, defaultF);
212 } else {
213 return static_cast<double>(x);
214 }
215 }, a);
216}
217
218// Dict Type
219
220#if defined(__cpp_lib_generic_unordered_lookup)
221// Custom transparent hasher for string-like types
223 using is_transparent = void;//enable transparent hasher
224 template<KeyT T>
225 std::size_t operator()(const T& key) const {
226 return std::hash<std::string_view>{}(key);
227 }
228};
229struct TransparentEqual {
230 using is_transparent = void;
231 template<typename T1, typename T2>
232 bool operator()(const T1& lhs, const T2& rhs) const noexcept {
234 return (lhs <=> rhs) == 0;
235 } else if constexpr (EqualityComparableT<T1> && EqualityComparableT<T2>) {
236 return lhs == rhs;
237 } else {
238 static_assert(sizeof(T1) == 0, "Types must be comparable");
239 }
240 }
241};
242using Dict = std::unordered_map<std::string, std::string, TransparentStringHash, TransparentEqual>;
243using DictAny = std::unordered_map<std::string, Any, TransparentStringHash, TransparentEqual>;
244using DictKeyT = std::string_view;
245#else
246using Dict = std::unordered_map<std::string, std::string>;
247using DictAny = std::unordered_map<std::string, Any>;
248using DictKeyT = const std::string&;
249#endif
250
251inline std::optional<std::string> dictAnyReadString(const DictAny &dict, DictKeyT key) {
252 auto it = dict.find(key);
253 if (it == dict.end()) [[unlikely]] {
254 return std::nullopt;
255 }
256 return {Any2String(it->second)};
257}
258
259inline auto dictAnyReadString(const DictAny &dict, DictKeyT key, const std::string &defaultS) {
260 return dictAnyReadString(dict, key).value_or(defaultS);
261}
262
263inline std::optional<int64_t> dictAnyReadInteger(const DictAny &dict, DictKeyT key) {
264 auto it = dict.find(key);
265 if (it == dict.end()) [[unlikely]] {
266 return std::nullopt;
267 }
268 return {Any2Integer(it->second)};
269}
270
272 return dictAnyReadInteger(dict, key).value_or(defaultI);
273}
274
275inline std::optional<double> dictAnyReadFloat(const DictAny &dict, DictKeyT key) {
276 auto it = dict.find(key);
277 if (it == dict.end()) [[unlikely]] {
278 return std::nullopt;
279 }
280 return {Any2Float(it->second)};
281}
282
283inline auto dictAnyReadFloat(const DictAny &dict, DictKeyT key, double defaultF) {
284 return dictAnyReadFloat(dict, key).value_or(defaultF);
285}
286
287// Bytes Type
288
289using BytesView = std::span<const byte>;
290using Bytes = std::vector<byte>;
291
292inline BytesView makeBytesView(const byte *data, size_t len) {
293 if (data == nullptr || len == 0) [[unlikely]] {
294 return {};
295 }
296 return {data, len};
297}
298
299inline Bytes makeBytes(const byte *data, size_t len) {
300 if (data == nullptr || len == 0) [[unlikely]] {
301 return {};
302 }
303 return {data, data + len};
304}
305
306template<CharacterT T>
307std::string makeStr(const T *ptr, size_t len = 0) {
308 if (ptr == nullptr) [[unlikely]] {
309 return {};
310 }
311 const auto cstr = reinterpret_cast<const char *>(ptr);
312 if (len == 0) {
313 return {cstr};
314 }
315 return {cstr, len};
316}
317
318// C String Utils
319
320inline std::optional<const char*> nullTerminatedCStr(std::string_view str) {
321 if (str.empty()) [[unlikely]] {
322 return std::nullopt;
323 }
324 return str.data();
325}
constexpr auto MinFloat128
Definition Types.hxx:168
constexpr auto MaxInt64
Definition Types.hxx:163
constexpr auto MaxFloat128
Definition Types.hxx:169
int32_t str2int32(const std::string &str, int32_t defaultI=MinInt32)
std::size_t getHash(const T &value)
Definition Types.hxx:137
constexpr auto MaxFloat32
Definition Types.hxx:165
To * dynamicCastX(From *ptr) noexcept
Definition Types.hxx:132
constexpr T MaxV()
Definition Types.hxx:156
std::string makeStr(const T *ptr, size_t len=0)
Definition Types.hxx:307
float str2float32(const std::string &str, float defaultF=MinFloat32)
constexpr auto MaxFloat64
Definition Types.hxx:167
std::optional< double > dictAnyReadFloat(const DictAny &dict, DictKeyT key)
Definition Types.hxx:275
constexpr auto MinFloat64
Definition Types.hxx:166
auto Any2String(const Any &v)
Definition Types.hxx:188
constexpr auto MaxInt32
Definition Types.hxx:161
const std::string & DictKeyT
Definition Types.hxx:248
std::unordered_map< std::string, Any > DictAny
Definition Types.hxx:247
std::variant< int64_t, double, std::string > Any
Definition Types.hxx:186
int64_t str2int64(const std::string &str, int64_t defaultI=MinInt64)
std::span< const byte > BytesView
Definition Types.hxx:289
void iterate(const T &container, std::function< void(const typename T::value_type &)> &&func)
Definition Types.hxx:142
std::vector< byte > Bytes
Definition Types.hxx:290
constexpr auto underlying(E e) noexcept -> std::underlying_type_t< E >
Definition Types.hxx:60
std::unordered_map< std::string, std::string > Dict
Definition Types.hxx:246
std::optional< std::string > dictAnyReadString(const DictAny &dict, DictKeyT key)
Definition Types.hxx:251
std::variant< int64_t, double > Num
Definition Types.hxx:185
Bytes makeBytes(const byte *data, size_t len)
Definition Types.hxx:299
constexpr auto MinInt32
Definition Types.hxx:160
auto Any2Integer(const Any &a, int64_t defaultI=MinInt64)
Definition Types.hxx:198
auto Any2Float(const Any &a, double defaultF=MinFloat64)
Definition Types.hxx:208
std::optional< int64_t > dictAnyReadInteger(const DictAny &dict, DictKeyT key)
Definition Types.hxx:263
double str2float64(const std::string &str, double defaultF=MinFloat64)
long double str2float128(const std::string &str, long double defaultF=MinFloat128)
constexpr auto MinFloat32
Definition Types.hxx:164
std::optional< const char * > nullTerminatedCStr(std::string_view str)
Definition Types.hxx:320
constexpr auto MinInt64
Definition Types.hxx:162
BytesView makeBytesView(const byte *data, size_t len)
Definition Types.hxx:292
constexpr T MinV()
Definition Types.hxx:151
Definition Types.hxx:57
Definition Types.hxx:49
Definition Types.hxx:90
Definition Types.hxx:29
Definition Types.hxx:71
Definition Types.hxx:46
Definition Types.hxx:96
Definition Types.hxx:43
Definition Types.hxx:84
Definition Types.hxx:110
Definition Types.hxx:40
Definition Types.hxx:103
Definition Types.hxx:66
Definition Types.hxx:81
Definition Types.hxx:35
Definition Types.hxx:117
Definition Types.hxx:74
Definition Types.hxx:124
Definition Types.hxx:32