9#include <condition_variable>
20#define KITTY_WHILE_LOOP(x, y, z) \
29template<
typename T,
typename U>
34#define KITTY_USING_MOVE_T(move_t, t, init_val, z) \
37 using element_type = typename argument_type<void(t)>::type; \
42 template<class... Args> \
43 move_t(Args &&...args): \
44 el {std::forward<Args>(args)...} { \
46 move_t(const move_t &) = delete; \
48 move_t(move_t &&other) noexcept: \
49 el {std::move(other.el)} { \
50 other.el = element_type {init_val}; \
53 move_t &operator=(const move_t &) = delete; \
55 move_t &operator=(move_t &&other) { \
56 std::swap(el, other.el); \
59 element_type *operator->() { \
62 const element_type *operator->() const { \
66 inline element_type release() { \
67 element_type val = std::move(el); \
68 el = element_type {init_val}; \
77#define KITTY_DECL_CONSTR(x) \
78 x(x &&) noexcept = default; \
79 x &operator=(x &&) noexcept = default; \
82#define KITTY_DEFAULT_CONSTR_MOVE(x) \
83 x(x &&) noexcept = default; \
84 x &operator=(x &&) noexcept = default;
86#define KITTY_DEFAULT_CONSTR_MOVE_THROW(x) \
88 x &operator=(x &&) = default; \
91#define KITTY_DEFAULT_CONSTR(x) \
92 KITTY_DEFAULT_CONSTR_MOVE(x) \
93 x(const x &) noexcept = default; \
94 x &operator=(const x &) = default;
96#define TUPLE_2D(a, b, expr) \
97 decltype(expr) a##_##b = expr; \
98 auto &a = std::get<0>(a##_##b); \
99 auto &b = std::get<1>(a##_##b)
101#define TUPLE_2D_REF(a, b, expr) \
102 auto &a##_##b = expr; \
103 auto &a = std::get<0>(a##_##b); \
104 auto &b = std::get<1>(a##_##b)
106#define TUPLE_3D(a, b, c, expr) \
107 decltype(expr) a##_##b##_##c = expr; \
108 auto &a = std::get<0>(a##_##b##_##c); \
109 auto &b = std::get<1>(a##_##b##_##c); \
110 auto &c = std::get<2>(a##_##b##_##c)
112#define TUPLE_3D_REF(a, b, c, expr) \
113 auto &a##_##b##_##c = expr; \
114 auto &a = std::get<0>(a##_##b##_##c); \
115 auto &b = std::get<1>(a##_##b##_##c); \
116 auto &c = std::get<2>(a##_##b##_##c)
118#define TUPLE_EL(a, b, expr) \
119 decltype(expr) a##_ = expr; \
120 auto &a = std::get<b>(a##_)
122#define TUPLE_EL_REF(a, b, expr) \
123 auto &a = std::get<b>(expr)
127 template<
template<
typename...>
class X,
class... Y>
130 template<
template<
typename...>
class X,
class... Y>
133 template<
template<
typename...>
class X,
class T,
class... Y>
136 template<
bool V,
class X,
class Y>
139 template<
class X,
class Y>
144 template<
class X,
class Y>
149 template<
bool V,
class X,
class Y>
152 template<
class... Ts>
154 using Ts::operator()...;
156 template<
class... Ts>
165 _func {std::forward<T>(f)} {
169 _func {std::move(other._func)} {
170 this->failure = other.failure;
172 other.failure =
false;
197 [[nodiscard]]
auto fail_guard(T &&f) {
202 void append_struct(std::vector<uint8_t> &buf,
const T &_struct) {
203 constexpr size_t data_len =
sizeof(_struct);
205 buf.reserve(data_len);
207 auto *data = (uint8_t *) &_struct;
209 for (
size_t x = 0; x < data_len; ++x) {
210 buf.push_back(data[x]);
220 const char _bits[16] {
239 char _hex[
sizeof(elem_type) * 2];
242 Hex(
const elem_type &elem,
bool rev) {
244 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem) +
sizeof(elem_type) - 1;
245 for (
auto it = begin(); it < cend();) {
246 *it++ = _bits[*data / 16];
247 *it++ = _bits[*data-- % 16];
250 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem);
251 for (
auto it = begin(); it < cend();) {
252 *it++ = _bits[*data / 16];
253 *it++ = _bits[*data++ % 16];
263 return _hex +
sizeof(elem_type) * 2;
266 const char *begin()
const {
270 const char *end()
const {
271 return _hex +
sizeof(elem_type) * 2;
274 const char *cbegin()
const {
278 const char *cend()
const {
279 return _hex +
sizeof(elem_type) * 2;
282 std::string to_string()
const {
283 return {begin(), end()};
286 std::string_view to_string_view()
const {
287 return {begin(),
sizeof(elem_type) * 2};
292 Hex<T> hex(
const T &elem,
bool rev =
false) {
297 std::string log_hex(
const T &value) {
298 return "0x" + Hex<T>(value,
false).to_string();
302 std::string hex_vec(It begin, It end,
bool rev =
false) {
303 auto str_size = 2 * std::distance(begin, end);
306 hex.resize(str_size);
308 const char _bits[16] {
328 for (
auto it = std::begin(hex); it < std::end(hex);) {
329 *it++ = _bits[((uint8_t) *begin) / 16];
330 *it++ = _bits[((uint8_t) *begin++) % 16];
334 for (
auto it = std::begin(hex); it < std::end(hex);) {
335 *it++ = _bits[((uint8_t) *end) / 16];
336 *it++ = _bits[((uint8_t) *end--) % 16];
344 std::string hex_vec(C &&c,
bool rev =
false) {
345 return hex_vec(std::begin(c), std::end(c), rev);
349 T from_hex(
const std::string_view &hex,
bool rev =
false) {
350 std::uint8_t buf[
sizeof(T)];
352 static char constexpr shift_bit =
'a' -
'A';
354 auto is_convertable = [](
char ch) ->
bool {
361 if (
'a' > ch || ch >
'z') {
368 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
369 auto padding =
sizeof(T) - buf_size;
371 const char *data = hex.data() + hex.size() - 1;
373 auto convert = [](
char ch) -> std::uint8_t {
374 if (ch >=
'0' && ch <=
'9') {
375 return (std::uint8_t) ch -
'0';
378 return (std::uint8_t)(ch | (char) 32) -
'a' + (char) 10;
381 std::fill_n(buf + buf_size, padding, 0);
383 std::for_each_n(buf, buf_size, [&](
auto &el) {
384 while (!is_convertable(*data)) {
387 std::uint8_t ch_r = convert(*data--);
389 while (!is_convertable(*data)) {
392 std::uint8_t ch_l = convert(*data--);
394 el = (ch_l << 4) | ch_r;
398 std::reverse(std::begin(buf), std::end(buf));
401 return *
reinterpret_cast<T *
>(buf);
404 inline std::string from_hex_vec(
const std::string &hex,
bool rev =
false) {
407 static char constexpr shift_bit =
'a' -
'A';
408 auto is_convertable = [](
char ch) ->
bool {
415 if (
'a' > ch || ch >
'z') {
422 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
423 buf.resize(buf_size);
425 const char *data = hex.data() + hex.size() - 1;
427 auto convert = [](
char ch) -> std::uint8_t {
428 if (ch >=
'0' && ch <=
'9') {
429 return (std::uint8_t) ch -
'0';
432 return (std::uint8_t)(ch | (char) 32) -
'a' + (char) 10;
435 for (
auto &el : buf) {
436 while (!is_convertable(*data)) {
439 std::uint8_t ch_r = convert(*data--);
441 while (!is_convertable(*data)) {
444 std::uint8_t ch_l = convert(*data--);
446 el = (ch_l << 4) | ch_r;
450 std::reverse(std::begin(buf), std::end(buf));
459 using value_type = T;
461 std::size_t operator()(
const value_type &value)
const {
462 const auto *p =
reinterpret_cast<const char *
>(&value);
464 return std::hash<std::string_view> {}(std::string_view {p,
sizeof(value_type)});
469 auto enm(
const T &val) ->
const std::underlying_type_t<T> & {
470 return *
reinterpret_cast<const std::underlying_type_t<T> *
>(&val);
474 auto enm(T &val) -> std::underlying_type_t<T> & {
475 return *
reinterpret_cast<std::underlying_type_t<T> *
>(&val);
478 inline std::int64_t from_chars(
const char *begin,
const char *end) {
484 std::int64_t mul = 1;
485 while (begin != --end) {
486 res += (std::int64_t)(*end -
'0') * mul;
491 return *begin !=
'-' ? res + (std::int64_t)(*begin -
'0') * mul : -res;
494 inline std::int64_t from_view(
const std::string_view &number) {
495 return from_chars(std::begin(number), std::end(number));
498 template<
class X,
class Y>
499 class Either:
public std::variant<std::monostate, X, Y> {
501 using std::variant<std::monostate, X, Y>::variant;
503 constexpr bool has_left()
const {
504 return std::holds_alternative<X>(*
this);
507 constexpr bool has_right()
const {
508 return std::holds_alternative<Y>(*
this);
512 return std::get<X>(*
this);
516 return std::get<Y>(*
this);
519 const X &left()
const {
520 return std::get<X>(*
this);
523 const Y &right()
const {
524 return std::get<Y>(*
this);
529 template<
typename T,
typename D = std::default_delete<T>>
532 using element_type = T;
533 using pointer = element_type *;
534 using const_pointer = element_type
const *;
535 using deleter_type = D;
541 constexpr uniq_ptr(std::nullptr_t)
noexcept:
551 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");
555 uniq_ptr(std::unique_ptr<V, deleter_type> &&uniq)
noexcept:
556 _p {uniq.release()} {
557 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");
562 _p {other.release()} {
563 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");
568 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");
569 reset(other.release());
575 uniq_ptr &operator=(std::unique_ptr<V, deleter_type> &&uniq)
noexcept {
576 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");
578 reset(uniq.release());
587 void reset(pointer p = pointer()) {
605 const_pointer get()
const {
609 std::add_lvalue_reference_t<element_type const> operator*()
const {
613 std::add_lvalue_reference_t<element_type> operator*() {
617 const_pointer operator->()
const {
621 pointer operator->() {
625 pointer *operator&()
const {
629 pointer *operator&() {
633 deleter_type &get_deleter() {
637 const deleter_type &get_deleter()
const {
641 explicit operator bool()
const {
642 return _p !=
nullptr;
647 deleter_type _deleter;
650 template<
class T1,
class D1,
class T2,
class D2>
652 return x.get() == y.get();
655 template<
class T1,
class D1,
class T2,
class D2>
656 bool operator!=(
const uniq_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
657 return x.get() != y.get();
660 template<
class T1,
class D1,
class T2,
class D2>
661 bool operator==(
const std::unique_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
662 return x.get() == y.get();
665 template<
class T1,
class D1,
class T2,
class D2>
666 bool operator!=(
const std::unique_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
667 return x.get() != y.get();
670 template<
class T1,
class D1,
class T2,
class D2>
671 bool operator==(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
672 return x.get() == y.get();
675 template<
class T1,
class D1,
class T2,
class D2>
676 bool operator!=(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
677 return x.get() != y.get();
680 template<
class T,
class D>
681 bool operator==(
const uniq_ptr<T, D> &x, std::nullptr_t) {
685 template<
class T,
class D>
686 bool operator!=(
const uniq_ptr<T, D> &x, std::nullptr_t) {
690 template<
class T,
class D>
691 bool operator==(std::nullptr_t,
const uniq_ptr<T, D> &y) {
695 template<
class T,
class D>
696 bool operator!=(std::nullptr_t,
const uniq_ptr<T, D> &y) {
701 using shared_t = std::shared_ptr<typename P::element_type>;
703 template<
class P,
class T>
704 shared_t<P> make_shared(T *pointer) {
705 return shared_t<P>(
reinterpret_cast<typename P::pointer
>(pointer),
typename P::deleter_type());
711 using element_type = T;
712 using pointer = element_type *;
713 using const_pointer = element_type
const *;
714 using reference = element_type &;
715 using const_reference = element_type
const &;
727 wrap_ptr(std::unique_ptr<element_type> &&uniq_p):
729 _p {uniq_p.release()} {
733 _own_ptr {other._own_ptr},
735 other._own_ptr =
false;
745 _own_ptr = other._own_ptr;
746 other._own_ptr =
false;
753 static_assert(std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
779 const_reference operator*()
const {
783 reference operator*() {
787 const_pointer operator->()
const {
791 pointer operator->() {
801 constexpr bool is_pointer_v =
802 instantiation_of_v<std::unique_ptr, T> ||
803 instantiation_of_v<std::shared_ptr, T> ||
804 instantiation_of_v<uniq_ptr, T> ||
805 std::is_pointer_v<T>;
807 template<
class T,
class V =
void>
811 struct __false_v<T, std::enable_if_t<instantiation_of_v<std::optional, T>>> {
812 static constexpr std::nullopt_t value = std::nullopt;
816 struct __false_v<T, std::enable_if_t<is_pointer_v<T>>> {
817 static constexpr std::nullptr_t value =
nullptr;
821 struct __false_v<T, std::enable_if_t<std::is_same_v<T, bool>>> {
822 static constexpr bool value =
false;
829 using optional_t = either_t<
830 (std::is_same_v<T, bool> || is_pointer_v<T>),
842 _buf {std::move(o._buf)} {
848 _buf {std::make_unique<T[]>(_els)} {
849 std::copy(o.begin(), o.end(), begin());
853 std::swap(_els, o._els);
854 std::swap(_buf, o._buf);
861 _buf {std::make_unique<T[]>(elements)} {
864 explicit buffer_t(
size_t elements,
const T &t):
866 _buf {std::make_unique<T[]>(elements)} {
867 std::fill_n(_buf.get(), elements, t);
870 T &operator[](
size_t el) {
874 const T &operator[](
size_t el)
const {
878 size_t size()
const {
882 void fake_resize(std::size_t els) {
890 const T *begin()
const {
895 return _buf.get() + _els;
898 const T *end()
const {
899 return _buf.get() + _els;
904 std::unique_ptr<T[]> _buf;
908 T either(std::optional<T> &&l, T &&r) {
910 return std::move(*l);
913 return std::forward<T>(r);
916 template<
class ReturnType,
class... Args>
918 typedef ReturnType (*type)(Args...);
921 template<class T, class ReturnType, typename Function<ReturnType, T>::type function>
925 void operator()(pointer p) {
930 template<class T, typename Function<void, T *>::type function>
934 template<class T, class ReturnType, typename Function<ReturnType, T *>::type function>
942 template<
class T,
class ReturnType, ReturnType (**function)(T *)>
947 template<
class T,
void (**function)(T *)>
948 using dyn_safe_ptr = safe_ptr<T, dynamic<T, void, function>>;
950 template<
class T,
class ReturnType, ReturnType (**function)(T *)>
951 using dyn_safe_ptr_v2 = safe_ptr<T, dynamic<T, ReturnType, function>>;
954 using c_ptr = safe_ptr<T, c_free<T>>;
957 std::string_view view(It begin, It end) {
958 return std::string_view {(
const char *) begin, (std::size_t)(end - begin)};
962 std::string_view view(
const T &data) {
963 return std::string_view((
const char *) &data,
sizeof(T));
970 friend std::ostream &operator<<(std::ostream &os,
const point_t &p) {
971 return (os <<
"Point(x: " << p.x <<
", y: " << p.y <<
")");
976 template<
class T =
void>
979#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
980 defined(__BIG_ENDIAN__) || \
981 defined(__ARMEB__) || \
982 defined(__THUMBEB__) || \
983 defined(__AARCH64EB__) || \
984 defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
987#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
988 defined(__LITTLE_ENDIAN__) || \
989 defined(__ARMEL__) || \
990 defined(__THUMBEL__) || \
991 defined(__AARCH64EL__) || \
992 defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
996 #error "Unknown Endianness"
1002 template<
class T,
class S =
void>
1006 struct endian_helper<T, std::enable_if_t<!(instantiation_of_v<std::optional, T>)>> {
1007 static inline T big(T x) {
1009 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
1011 std::reverse(data, data +
sizeof(x));
1017 static inline T little(T x) {
1019 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
1021 std::reverse(data, data +
sizeof(x));
1029 struct endian_helper<T, std::enable_if_t<instantiation_of_v<std::optional, T>>> {
1030 static inline T little(T x) {
1036 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1038 std::reverse(data, data +
sizeof(*x));
1044 static inline T big(T x) {
1050 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1052 std::reverse(data, data +
sizeof(*x));
1060 inline auto little(T x) {
1065 inline auto big(T x) {
1066 return endian_helper<T>::big(x);
Definition utility.h:1003
@ little
little-endian target architecture
Definition utility.h:994
@ big
big-endian target architecture
Definition utility.h:998