8#include <condition_variable>
19#define KITTY_WHILE_LOOP(x, y, z) \
28template <
typename T,
typename U>
33#define KITTY_USING_MOVE_T(move_t, t, init_val, z) \
36 using element_type = typename argument_type<void(t)>::type; \
38 move_t(): el { init_val } {} \
39 template <class... Args> \
40 move_t(Args &&...args): el { std::forward<Args>(args)... } {} \
41 move_t(const move_t &) = delete; \
43 move_t(move_t &&other) noexcept: el { std::move(other.el) } { \
44 other.el = element_type { init_val }; \
48 operator=(const move_t &) = delete; \
51 operator=(move_t &&other) { \
52 std::swap(el, other.el); \
56 operator->() { return ⪙ } \
57 const element_type * \
58 operator->() const { return ⪙ } \
62 element_type val = std::move(el); \
63 el = element_type { init_val }; \
72#define KITTY_DECL_CONSTR(x) \
73 x(x &&) noexcept = default; \
74 x &operator=(x &&) noexcept = default; \
77#define KITTY_DEFAULT_CONSTR_MOVE(x) \
78 x(x &&) noexcept = default; \
79 x &operator=(x &&) noexcept = default;
81#define KITTY_DEFAULT_CONSTR_MOVE_THROW(x) \
83 x &operator=(x &&) = default; \
86#define KITTY_DEFAULT_CONSTR(x) \
87 KITTY_DEFAULT_CONSTR_MOVE(x) \
88 x(const x &) noexcept = default; \
89 x &operator=(const x &) = default;
91#define TUPLE_2D(a, b, expr) \
92 decltype(expr) a##_##b = expr; \
93 auto &a = std::get<0>(a##_##b); \
94 auto &b = std::get<1>(a##_##b)
96#define TUPLE_2D_REF(a, b, expr) \
97 auto &a##_##b = expr; \
98 auto &a = std::get<0>(a##_##b); \
99 auto &b = std::get<1>(a##_##b)
101#define TUPLE_3D(a, b, c, expr) \
102 decltype(expr) a##_##b##_##c = expr; \
103 auto &a = std::get<0>(a##_##b##_##c); \
104 auto &b = std::get<1>(a##_##b##_##c); \
105 auto &c = std::get<2>(a##_##b##_##c)
107#define TUPLE_3D_REF(a, b, c, expr) \
108 auto &a##_##b##_##c = expr; \
109 auto &a = std::get<0>(a##_##b##_##c); \
110 auto &b = std::get<1>(a##_##b##_##c); \
111 auto &c = std::get<2>(a##_##b##_##c)
113#define TUPLE_EL(a, b, expr) \
114 decltype(expr) a##_ = expr; \
115 auto &a = std::get<b>(a##_)
117#define TUPLE_EL_REF(a, b, expr) \
118 auto &a = std::get<b>(expr)
122 template <
template <
typename...>
class X,
class... Y>
125 template <
template <
typename...>
class X,
class... Y>
128 template <
template <
typename...>
class X,
class T,
class... Y>
131 template <
bool V,
class X,
class Y>
134 template <
class X,
class Y>
139 template <
class X,
class Y>
144 template <
bool V,
class X,
class Y>
147 template <
class... Ts>
149 using Ts::operator()...;
151 template <
class... Ts>
159 _func { std::forward<T>(f) } {}
161 _func { std::move(other._func) } {
162 this->failure = other.failure;
164 other.failure =
false;
181 disable() { failure =
false; }
182 bool failure {
true };
196 append_struct(std::vector<uint8_t> &buf,
const T &_struct) {
197 constexpr size_t data_len =
sizeof(_struct);
199 buf.reserve(data_len);
201 auto *data = (uint8_t *) &_struct;
203 for (
size_t x = 0; x < data_len; ++x) {
204 buf.push_back(data[x]);
214 const char _bits[16] {
215 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'
218 char _hex[
sizeof(elem_type) * 2];
221 Hex(
const elem_type &elem,
bool rev) {
223 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem) +
sizeof(elem_type) - 1;
224 for (
auto it = begin(); it < cend();) {
225 *it++ = _bits[*data / 16];
226 *it++ = _bits[*data-- % 16];
230 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem);
231 for (
auto it = begin(); it < cend();) {
232 *it++ = _bits[*data / 16];
233 *it++ = _bits[*data++ % 16];
239 begin() {
return _hex; }
241 end() {
return _hex +
sizeof(elem_type) * 2; }
244 begin()
const {
return _hex; }
246 end()
const {
return _hex +
sizeof(elem_type) * 2; }
249 cbegin()
const {
return _hex; }
251 cend()
const {
return _hex +
sizeof(elem_type) * 2; }
255 return { begin(), end() };
259 to_string_view()
const {
260 return { begin(),
sizeof(elem_type) * 2 };
266 hex(
const T &elem,
bool rev =
false) {
270 template <
typename T>
272 log_hex(
const T &value) {
273 return "0x" + Hex<T>(value,
false).to_string();
278 hex_vec(It begin, It end,
bool rev =
false) {
279 auto str_size = 2 * std::distance(begin, end);
282 hex.resize(str_size);
284 const char _bits[16] {
285 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'
289 for (
auto it = std::begin(hex); it < std::end(hex);) {
290 *it++ = _bits[((uint8_t) *begin) / 16];
291 *it++ = _bits[((uint8_t) *begin++) % 16];
296 for (
auto it = std::begin(hex); it < std::end(hex);) {
297 *it++ = _bits[((uint8_t) *end) / 16];
298 *it++ = _bits[((uint8_t) *end--) % 16];
307 hex_vec(C &&c,
bool rev =
false) {
308 return hex_vec(std::begin(c), std::end(c), rev);
313 from_hex(
const std::string_view &hex,
bool rev =
false) {
314 std::uint8_t buf[
sizeof(T)];
316 static char constexpr shift_bit =
'a' -
'A';
318 auto is_convertable = [](
char ch) ->
bool {
325 if (
'a' > ch || ch >
'z') {
332 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
333 auto padding =
sizeof(T) - buf_size;
335 const char *data = hex.data() + hex.size() - 1;
337 auto convert = [](
char ch) -> std::uint8_t {
338 if (ch >=
'0' && ch <=
'9') {
339 return (std::uint8_t) ch -
'0';
342 return (std::uint8_t)(ch | (char) 32) -
'a' + (char) 10;
345 std::fill_n(buf + buf_size, padding, 0);
347 std::for_each_n(buf, buf_size, [&](
auto &el) {
348 while (!is_convertable(*data)) { --data; }
349 std::uint8_t ch_r = convert(*data--);
351 while (!is_convertable(*data)) { --data; }
352 std::uint8_t ch_l = convert(*data--);
354 el = (ch_l << 4) | ch_r;
358 std::reverse(std::begin(buf), std::end(buf));
361 return *
reinterpret_cast<T *
>(buf);
365 from_hex_vec(
const std::string &hex,
bool rev =
false) {
368 static char constexpr shift_bit =
'a' -
'A';
369 auto is_convertable = [](
char ch) ->
bool {
376 if (
'a' > ch || ch >
'z') {
383 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
384 buf.resize(buf_size);
386 const char *data = hex.data() + hex.size() - 1;
388 auto convert = [](
char ch) -> std::uint8_t {
389 if (ch >=
'0' && ch <=
'9') {
390 return (std::uint8_t) ch -
'0';
393 return (std::uint8_t)(ch | (char) 32) -
'a' + (char) 10;
396 for (
auto &el : buf) {
397 while (!is_convertable(*data)) { --data; }
398 std::uint8_t ch_r = convert(*data--);
400 while (!is_convertable(*data)) { --data; }
401 std::uint8_t ch_l = convert(*data--);
403 el = (ch_l << 4) | ch_r;
407 std::reverse(std::begin(buf), std::end(buf));
416 using value_type = T;
418 operator()(
const value_type &value)
const {
419 const auto *p =
reinterpret_cast<const char *
>(&value);
421 return std::hash<std::string_view> {}(std::string_view { p,
sizeof(value_type) });
427 enm(
const T &val) ->
const std::underlying_type_t<T> & {
428 return *
reinterpret_cast<const std::underlying_type_t<T> *
>(&val);
433 enm(T &val) -> std::underlying_type_t<T> & {
434 return *
reinterpret_cast<std::underlying_type_t<T> *
>(&val);
438 from_chars(
const char *begin,
const char *end) {
444 std::int64_t mul = 1;
445 while (begin != --end) {
446 res += (std::int64_t)(*end -
'0') * mul;
451 return *begin !=
'-' ? res + (std::int64_t)(*begin -
'0') * mul : -res;
455 from_view(
const std::string_view &number) {
456 return from_chars(std::begin(number), std::end(number));
459 template <
class X,
class Y>
460 class Either:
public std::variant<std::monostate, X, Y> {
462 using std::variant<std::monostate, X, Y>::variant;
466 return std::holds_alternative<X>(*
this);
470 return std::holds_alternative<Y>(*
this);
475 return std::get<X>(*
this);
480 return std::get<Y>(*
this);
485 return std::get<X>(*
this);
490 return std::get<Y>(*
this);
495 template <
typename T,
typename D = std::default_delete<T>>
498 using element_type = T;
499 using pointer = element_type *;
500 using const_pointer = element_type
const *;
501 using deleter_type = D;
505 constexpr uniq_ptr(std::nullptr_t)
noexcept:
510 operator=(
const uniq_ptr &other)
noexcept =
delete;
515 static_assert(std::is_same_v<element_type, void> || std::is_same_v<element_type, V> || std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
519 uniq_ptr(std::unique_ptr<V, deleter_type> &&uniq)
noexcept:
520 _p { uniq.release() } {
521 static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
526 _p { other.release() } {
527 static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
533 static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
534 reset(other.release());
541 operator=(std::unique_ptr<V, deleter_type> &&uniq)
noexcept {
542 static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
544 reset(uniq.release());
554 reset(pointer p = pointer()) {
579 std::add_lvalue_reference_t<element_type const>
583 std::add_lvalue_reference_t<element_type>
611 get_deleter()
const {
616 operator bool()
const {
617 return _p !=
nullptr;
622 deleter_type _deleter;
625 template <
class T1,
class D1,
class T2,
class D2>
628 return x.get() == y.get();
631 template <
class T1,
class D1,
class T2,
class D2>
633 operator!=(
const uniq_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
634 return x.get() != y.get();
637 template <
class T1,
class D1,
class T2,
class D2>
639 operator==(
const std::unique_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
640 return x.get() == y.get();
643 template <
class T1,
class D1,
class T2,
class D2>
645 operator!=(
const std::unique_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
646 return x.get() != y.get();
649 template <
class T1,
class D1,
class T2,
class D2>
651 operator==(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
652 return x.get() == y.get();
655 template <
class T1,
class D1,
class T2,
class D2>
657 operator!=(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
658 return x.get() != y.get();
661 template <
class T,
class D>
663 operator==(
const uniq_ptr<T, D> &x, std::nullptr_t) {
667 template <
class T,
class D>
669 operator!=(
const uniq_ptr<T, D> &x, std::nullptr_t) {
673 template <
class T,
class D>
675 operator==(std::nullptr_t,
const uniq_ptr<T, D> &y) {
679 template <
class T,
class D>
681 operator!=(std::nullptr_t,
const uniq_ptr<T, D> &y) {
686 using shared_t = std::shared_ptr<typename P::element_type>;
688 template <
class P,
class T>
690 make_shared(T *pointer) {
691 return shared_t<P>(
reinterpret_cast<typename P::pointer
>(pointer),
typename P::deleter_type());
697 using element_type = T;
698 using pointer = element_type *;
699 using const_pointer = element_type
const *;
700 using reference = element_type &;
701 using const_reference = element_type
const &;
704 _own_ptr {
false }, _p {
nullptr } {}
706 _own_ptr {
false }, _p { p } {}
707 wrap_ptr(std::unique_ptr<element_type> &&uniq_p):
708 _own_ptr {
true }, _p { uniq_p.release() } {}
710 _own_ptr { other._own_ptr }, _p { other._p } {
711 other._own_ptr =
false;
715 operator=(
wrap_ptr &&other)
noexcept {
722 _own_ptr = other._own_ptr;
723 other._own_ptr =
false;
730 operator=(std::unique_ptr<V> &&
uniq_ptr) {
731 static_assert(std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
739 operator=(pointer p) {
781 constexpr bool is_pointer_v =
782 instantiation_of_v<std::unique_ptr, T> ||
783 instantiation_of_v<std::shared_ptr, T> ||
784 instantiation_of_v<uniq_ptr, T> ||
785 std::is_pointer_v<T>;
787 template <
class T,
class V =
void>
791 struct __false_v<T, std::enable_if_t<instantiation_of_v<std::optional, T>>> {
792 static constexpr std::nullopt_t value = std::nullopt;
796 struct __false_v<T, std::enable_if_t<is_pointer_v<T>>> {
797 static constexpr std::nullptr_t value =
nullptr;
801 struct __false_v<T, std::enable_if_t<std::is_same_v<T, bool>>> {
802 static constexpr bool value =
false;
809 using optional_t = either_t<
810 (std::is_same_v<T, bool> || is_pointer_v<T>),
811 T, std::optional<T>>;
819 _els { o._els }, _buf { std::move(o._buf) } {
823 _els { o._els }, _buf { std::make_unique<T[]>(_els) } {
824 std::copy(o.begin(), o.end(), begin());
828 std::swap(_els, o._els);
829 std::swap(_buf, o._buf);
835 _els { elements }, _buf { std::make_unique<T[]>(elements) } {}
836 explicit buffer_t(
size_t elements,
const T &t):
837 _els { elements }, _buf { std::make_unique<T[]>(elements) } {
838 std::fill_n(_buf.get(), elements, t);
842 operator[](
size_t el) {
847 operator[](
size_t el)
const {
857 fake_resize(std::size_t els) {
873 return _buf.get() + _els;
878 return _buf.get() + _els;
883 std::unique_ptr<T[]> _buf;
888 either(std::optional<T> &&l, T &&r) {
890 return std::move(*l);
893 return std::forward<T>(r);
896 template <
class ReturnType,
class... Args>
898 typedef ReturnType (*type)(Args...);
901 template <class T, class ReturnType, typename Function<ReturnType, T>::type function>
906 operator()(pointer p) {
911 template <class T, typename Function<void, T *>::type function>
915 template <class T, class ReturnType, typename Function<ReturnType, T *>::type function>
924 template <
class T,
class ReturnType, ReturnType (**function)(T *)>
930 template <
class T,
void (**function)(T *)>
931 using dyn_safe_ptr = safe_ptr<T, dynamic<T, void, function>>;
933 template <
class T,
class ReturnType, ReturnType (**function)(T *)>
934 using dyn_safe_ptr_v2 = safe_ptr<T, dynamic<T, ReturnType, function>>;
937 using c_ptr = safe_ptr<T, c_free<T>>;
941 view(It begin, It end) {
942 return std::string_view { (
const char *) begin, (std::size_t)(end - begin) };
947 view(
const T &data) {
948 return std::string_view((
const char *) &data,
sizeof(T));
955 friend std::ostream &
956 operator<<(std::ostream &os,
const point_t &p) {
957 return (os <<
"Point(x: " << p.x <<
", y: " << p.y <<
")");
962 template <
class T =
void>
965#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
966 defined(__BIG_ENDIAN__) || \
967 defined(__ARMEB__) || \
968 defined(__THUMBEB__) || \
969 defined(__AARCH64EB__) || \
970 defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
973#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
974 defined(__LITTLE_ENDIAN__) || \
975 defined(__ARMEL__) || \
976 defined(__THUMBEL__) || \
977 defined(__AARCH64EL__) || \
978 defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
982 #error "Unknown Endianness"
988 template <
class T,
class S =
void>
993 !(instantiation_of_v<std::optional, T>)>> {
997 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
999 std::reverse(data, data +
sizeof(x));
1008 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
1010 std::reverse(data, data +
sizeof(x));
1019 instantiation_of_v<std::optional, T>>> {
1025 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1027 std::reverse(data, data +
sizeof(*x));
1038 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1040 std::reverse(data, data +
sizeof(*x));
1053 big(T x) {
return endian_helper<T>::big(x); }
@ little
little-endian target architecture
Definition utility.h:980
@ big
big-endian target architecture
Definition utility.h:984