9#include <condition_variable>
24#define KITTY_WHILE_LOOP(x, y, z) \
36template<
typename T,
typename U>
48#define KITTY_USING_MOVE_T(move_t, t, init_val, z) \
57 using element_type = typename argument_type<void(t)>::type; \
70 template<class... Args> \
71 move_t(Args &&...args): \
72 el {std::forward<Args>(args)...} { \
77 move_t(const move_t &) = delete; \
84 move_t(move_t &&other) noexcept: \
85 el {std::move(other.el)} { \
86 other.el = element_type {init_val}; \
92 move_t &operator=(const move_t &) = delete; \
100 move_t &operator=(move_t &&other) { \
101 std::swap(el, other.el); \
109 element_type *operator->() { \
117 const element_type *operator->() const { \
126 inline element_type release() { \
127 element_type val = std::move(el); \
128 el = element_type {init_val}; \
147#define KITTY_DECL_CONSTR(x) \
151 x(x &&) noexcept = default; \
157 x &operator=(x &&) noexcept = default; \
167#define KITTY_DEFAULT_CONSTR_MOVE(x) \
171 x(x &&) noexcept = default; \
177 x &operator=(x &&) noexcept = default;
183#define KITTY_DEFAULT_CONSTR_MOVE_THROW(x) \
193 x &operator=(x &&) = default; \
203#define KITTY_DEFAULT_CONSTR(x) \
204 KITTY_DEFAULT_CONSTR_MOVE(x) \
208 x(const x &) noexcept = default; \
214 x &operator=(const x &) = default;
220#define TUPLE_2D(a, b, expr) \
221 decltype(expr) a##_##b = expr; \
222 auto &a = std::get<0>(a##_##b); \
223 auto &b = std::get<1>(a##_##b)
229#define TUPLE_2D_REF(a, b, expr) \
230 auto &a##_##b = expr; \
231 auto &a = std::get<0>(a##_##b); \
232 auto &b = std::get<1>(a##_##b)
238#define TUPLE_3D(a, b, c, expr) \
239 decltype(expr) a##_##b##_##c = expr; \
240 auto &a = std::get<0>(a##_##b##_##c); \
241 auto &b = std::get<1>(a##_##b##_##c); \
242 auto &c = std::get<2>(a##_##b##_##c)
248#define TUPLE_3D_REF(a, b, c, expr) \
249 auto &a##_##b##_##c = expr; \
250 auto &a = std::get<0>(a##_##b##_##c); \
251 auto &b = std::get<1>(a##_##b##_##c); \
252 auto &c = std::get<2>(a##_##b##_##c)
258#define TUPLE_EL(a, b, expr) \
259 decltype(expr) a##_ = expr; \
260 auto &a = std::get<b>(a##_)
266#define TUPLE_EL_REF(a, b, expr) \
267 auto &a = std::get<b>(expr)
271 template<
template<
typename...>
class X,
class... Y>
274 template<
template<
typename...>
class X,
class... Y>
277 template<
template<
typename...>
class X,
class T,
class... Y>
280 template<
bool V,
class X,
class Y>
286 template<
class X,
class Y>
297 template<
class X,
class Y>
308 template<
bool V,
class X,
class Y>
311 template<
class... Ts>
313 using Ts::operator()...;
318 template<
class... Ts>
319 overloaded(Ts...) -> overloaded<Ts...>;
335 _func {std::forward<T>(f)} {
344 _func {std::move(other._func)} {
347 other.failure =
false;
382 return FailGuard<T> {std::forward<T>(f)};
392 void append_struct(std::vector<uint8_t> &buf,
const T &_struct) {
393 constexpr size_t data_len =
sizeof(_struct);
395 buf.reserve(data_len);
397 auto *data = (uint8_t *) &_struct;
399 for (
size_t x = 0; x < data_len; ++x) {
400 buf.push_back(data[x]);
416 const char _bits[16] {
446 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem) +
sizeof(
elem_type) - 1;
448 *it++ = _bits[*data / 16];
449 *it++ = _bits[*data-- % 16];
452 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(&elem);
454 *it++ = _bits[*data / 16];
455 *it++ = _bits[*data++ % 16];
483 const char *
begin()
const {
492 const char *
end()
const {
501 const char *
cbegin()
const {
510 const char *
cend()
const {
541 Hex<T>
hex(
const T &elem,
bool rev =
false) {
542 return Hex<T>(elem, rev);
552 std::string
log_hex(
const T &value) {
553 return "0x" + Hex<T>(value,
false).to_string();
565 std::string
hex_vec(It begin, It end,
bool rev =
false) {
566 auto str_size = 2 * std::distance(begin, end);
569 hex.resize(str_size);
571 const char _bits[16] {
591 for (
auto it = std::begin(hex); it < std::end(hex);) {
592 *it++ = _bits[((uint8_t) *begin) / 16];
593 *it++ = _bits[((uint8_t) *begin++) % 16];
597 for (
auto it = std::begin(hex); it < std::end(hex);) {
598 *it++ = _bits[((uint8_t) *end) / 16];
599 *it++ = _bits[((uint8_t) *end--) % 16];
614 std::string
hex_vec(C &&c,
bool rev =
false) {
615 return hex_vec(std::begin(c), std::end(c), rev);
626 T
from_hex(
const std::string_view &hex,
bool rev =
false) {
627 std::uint8_t buf[
sizeof(T)];
629 static char constexpr shift_bit =
'a' -
'A';
631 auto is_convertable = [](
char ch) ->
bool {
638 if (
'a' > ch || ch >
'z') {
645 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
646 auto padding =
sizeof(T) - buf_size;
648 const char *data =
hex.data() +
hex.size() - 1;
650 auto convert = [](
char ch) -> std::uint8_t {
651 if (ch >=
'0' && ch <=
'9') {
652 return (std::uint8_t) ch -
'0';
655 return (std::uint8_t) (ch | (char) 32) -
'a' + (
char) 10;
658 std::fill_n(buf + buf_size, padding, 0);
660 std::for_each_n(buf, buf_size, [&](
auto &el) {
661 while (!is_convertable(*data)) {
664 std::uint8_t ch_r = convert(*data--);
666 while (!is_convertable(*data)) {
669 std::uint8_t ch_l = convert(*data--);
671 el = (ch_l << 4) | ch_r;
675 std::reverse(std::begin(buf), std::end(buf));
678 return *
reinterpret_cast<T *
>(buf);
688 inline std::string
from_hex_vec(
const std::string &hex,
bool rev =
false) {
691 static char constexpr shift_bit =
'a' -
'A';
692 auto is_convertable = [](
char ch) ->
bool {
699 if (
'a' > ch || ch >
'z') {
706 auto buf_size = std::count_if(std::begin(hex), std::end(hex), is_convertable) / 2;
707 buf.resize(buf_size);
709 const char *data = hex.data() + hex.size() - 1;
711 auto convert = [](
char ch) -> std::uint8_t {
712 if (ch >=
'0' && ch <=
'9') {
713 return (std::uint8_t) ch -
'0';
716 return (std::uint8_t) (ch | (char) 32) -
'a' + (
char) 10;
719 for (
auto &el : buf) {
720 while (!is_convertable(*data)) {
723 std::uint8_t ch_r = convert(*data--);
725 while (!is_convertable(*data)) {
728 std::uint8_t ch_l = convert(*data--);
730 el = (ch_l << 4) | ch_r;
734 std::reverse(std::begin(buf), std::end(buf));
758 const auto *p =
reinterpret_cast<const char *
>(&value);
760 return std::hash<std::string_view> {}(std::string_view {p,
sizeof(
value_type)});
771 auto enm(
const T &val) ->
const std::underlying_type_t<T> & {
772 return *
reinterpret_cast<const std::underlying_type_t<T> *
>(&val);
782 auto enm(T &val) -> std::underlying_type_t<T> & {
783 return *
reinterpret_cast<std::underlying_type_t<T> *
>(&val);
793 inline std::int64_t
from_chars(
const char *begin,
const char *end) {
799 std::int64_t mul = 1;
800 while (begin != --end) {
801 res += (std::int64_t) (*end -
'0') * mul;
806 return *begin !=
'-' ? res + (std::int64_t) (*begin -
'0') * mul : -res;
815 inline std::int64_t from_view(
const std::string_view &number) {
816 return from_chars(std::begin(number), std::end(number));
822 template<
class X,
class Y>
823 class Either:
public std::variant<std::monostate, X, Y> {
825 using std::variant<std::monostate, X, Y>::variant;
833 return std::holds_alternative<X>(*
this);
842 return std::holds_alternative<Y>(*
this);
851 return std::get<X>(*
this);
860 return std::get<Y>(*
this);
868 const X &
left()
const {
869 return std::get<X>(*
this);
877 const Y &
right()
const {
878 return std::get<Y>(*
this);
886 template<
typename T,
typename D = std::default_delete<T>>
913 constexpr uniq_ptr(std::nullptr_t)
noexcept:
917 uniq_ptr(
const uniq_ptr &other)
noexcept =
delete;
918 uniq_ptr &operator=(
const uniq_ptr &other)
noexcept =
delete;
926 uniq_ptr(V *p)
noexcept:
928 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");
937 uniq_ptr(std::unique_ptr<V, deleter_type> &&uniq)
noexcept:
938 _p {uniq.release()} {
939 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");
949 _p {other.release()} {
950 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");
960 uniq_ptr &operator=(uniq_ptr<V, deleter_type> &&other)
noexcept {
961 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");
962 reset(other.release());
974 uniq_ptr &operator=(std::unique_ptr<V, deleter_type> &&uniq)
noexcept {
975 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");
977 reset(uniq.release());
1033 std::add_lvalue_reference_t<element_type const>
operator*()
const {
1103 explicit operator bool()
const {
1104 return _p !=
nullptr;
1119 template<
class T1,
class D1,
class T2,
class D2>
1120 bool operator==(
const uniq_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
1121 return x.get() == y.get();
1131 template<
class T1,
class D1,
class T2,
class D2>
1132 bool operator!=(
const uniq_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
1133 return x.get() != y.get();
1143 template<
class T1,
class D1,
class T2,
class D2>
1145 return x.get() == y.
get();
1155 template<
class T1,
class D1,
class T2,
class D2>
1156 bool operator!=(
const std::unique_ptr<T1, D1> &x,
const uniq_ptr<T2, D2> &y) {
1157 return x.get() != y.get();
1167 template<
class T1,
class D1,
class T2,
class D2>
1168 bool operator==(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
1169 return x.get() == y.get();
1179 template<
class T1,
class D1,
class T2,
class D2>
1180 bool operator!=(
const uniq_ptr<T1, D1> &x,
const std::unique_ptr<T1, D1> &y) {
1181 return x.get() != y.get();
1190 template<
class T,
class D>
1201 template<
class T,
class D>
1212 template<
class T,
class D>
1223 template<
class T,
class D>
1232 using shared_t = std::shared_ptr<typename P::element_type>;
1240 template<
class P,
class T>
1242 return shared_t<P>(
reinterpret_cast<typename P::pointer
>(pointer),
typename P::deleter_type());
1292 wrap_ptr(std::unique_ptr<element_type> &&uniq_p):
1294 _p {uniq_p.release()} {
1302 wrap_ptr(wrap_ptr &&other):
1303 _own_ptr {other._own_ptr},
1305 other._own_ptr =
false;
1321 _own_ptr = other._own_ptr;
1322 other._own_ptr =
false;
1335 static_assert(std::is_base_of_v<element_type, V>,
"element_type must be base class of V");
1413 instantiation_of_v<std::unique_ptr, T> ||
1414 instantiation_of_v<std::shared_ptr, T> ||
1415 instantiation_of_v<uniq_ptr, T> ||
1416 std::is_pointer_v<T>;
1418 template<
class T,
class V =
void>
1425 struct __false_v<T, std::enable_if_t<instantiation_of_v<std::optional, T>>> {
1426 static constexpr std::nullopt_t value = std::nullopt;
1433 struct __false_v<T, std::enable_if_t<is_pointer_v<T>>> {
1434 static constexpr std::nullptr_t value =
nullptr;
1441 struct __false_v<T, std::enable_if_t<std::is_same_v<T, bool>>> {
1442 static constexpr bool value =
false;
1446 static constexpr auto false_v = __false_v<T>::value;
1453 (std::is_same_v<T, bool> || is_pointer_v<T>),
1473 _buf {std::move(o._buf)} {
1482 buffer_t(
const buffer_t &o):
1484 _buf {std::make_unique<T[]>(_els)} {
1485 std::copy(o.begin(), o.end(),
begin());
1494 buffer_t &
operator=(buffer_t &&o)
noexcept {
1495 std::swap(_els, o._els);
1496 std::swap(_buf, o._buf);
1506 explicit buffer_t(
size_t elements):
1508 _buf {std::make_unique<T[]>(elements)} {
1519 _buf {std::make_unique<T[]>(elements)} {
1520 std::fill_n(_buf.get(), elements, t);
1548 size_t size()
const {
1575 const T *
begin()
const {
1585 return _buf.get() + _els;
1594 return _buf.get() + _els;
1599 std::unique_ptr<T[]> _buf;
1610 T
either(std::optional<T> &&l, T &&r) {
1612 return std::move(*l);
1615 return std::forward<T>(r);
1621 template<
class ReturnType,
class... Args>
1626 typedef ReturnType (*
type)(Args...);
1632 template<class T, class ReturnType, typename Function<ReturnType, T>::type function>
1652 template<class T, typename Function<void, T *>::type function>
1659 template<class T, class ReturnType, typename Function<ReturnType, T *>::type function>
1677 template<
class T,
class ReturnType, ReturnType (**function)(T *)>
1685 template<
class T,
void (**function)(T *)>
1686 using dyn_safe_ptr = safe_ptr<T, dynamic<T, void, function>>;
1691 template<
class T,
class ReturnType, ReturnType (**function)(T *)>
1692 using dyn_safe_ptr_v2 = safe_ptr<T, dynamic<T, ReturnType, function>>;
1708 std::string_view
view(It begin, It end) {
1709 return std::string_view {(
const char *) begin, (std::size_t) (end - begin)};
1719 std::string_view
view(
const T &data) {
1720 return std::string_view((
const char *) &data,
sizeof(T));
1734 return (os <<
"Point(x: " << p.
x <<
", y: " << p.
y <<
")");
1742 template<
class T =
void>
1745#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
1746 defined(__BIG_ENDIAN__) || \
1747 defined(__ARMEB__) || \
1748 defined(__THUMBEB__) || \
1749 defined(__AARCH64EB__) || \
1750 defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
1753#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
1754 defined(__LITTLE_ENDIAN__) || \
1755 defined(__ARMEL__) || \
1756 defined(__THUMBEL__) || \
1757 defined(__AARCH64EL__) || \
1758 defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
1762 #error "Unknown Endianness"
1768 template<
class T,
class S =
void>
1769 struct endian_helper {};
1775 struct endian_helper<T, std::enable_if_t<!(instantiation_of_v<std::optional, T>)>> {
1782 static inline T big(T x) {
1784 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
1786 std::reverse(data, data +
sizeof(x));
1798 static inline T
little(T x) {
1800 uint8_t *data =
reinterpret_cast<uint8_t *
>(&x);
1802 std::reverse(data, data +
sizeof(x));
1813 struct endian_helper<T, std::enable_if_t<instantiation_of_v<std::optional, T>>> {
1820 static inline T little(T x) {
1826 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1828 std::reverse(data, data +
sizeof(*x));
1840 static inline T
big(T x) {
1846 auto *data =
reinterpret_cast<uint8_t *
>(&*x);
1848 std::reverse(data, data +
sizeof(*x));
1862 inline auto little(T x) {
1863 return endian_helper<T>::little(x);
1873 inline auto big(T x) {
1874 return endian_helper<T>::big(x);
util::buffer_t< std::uint8_t > buffer_t
Byte buffer used for encoded audio packet payloads.
Definition audio.h:92
X & left()
Return the left-hand alternative held by the variant.
Definition utility.h:783
constexpr bool has_right() const
Check whether right.
Definition utility.h:774
constexpr bool has_left() const
Check whether left.
Definition utility.h:765
Y & right()
Return the right-hand alternative held by the variant.
Definition utility.h:792
Scope guard that runs a cleanup action unless it is disabled.
Definition utility.h:258
void disable()
Disable the fail guard so destruction will not run the cleanup action.
Definition utility.h:297
bool failure
Whether the fail guard should run its cleanup action.
Definition utility.h:301
Formatter that exposes a value's bytes as hexadecimal text.
Definition utility.h:341
char * end()
Return an iterator one past the final byte in the buffer view.
Definition utility.h:407
std::string to_string() const
Convert to string.
Definition utility.h:452
T elem_type
Integral type used for one formatted hex element.
Definition utility.h:346
const char * cend() const
Return a const iterator one past the last byte in the view.
Definition utility.h:443
char * begin()
Return an iterator to the first byte in the buffer view.
Definition utility.h:398
std::string_view to_string_view() const
Convert to string view.
Definition utility.h:461
const char * cbegin() const
Return a const iterator to the first byte in the view.
Definition utility.h:434
Hex(const elem_type &elem, bool rev)
Construct a hexadecimal byte view for the supplied value.
Definition utility.h:377
Owning contiguous buffer with an explicit logical element count.
Definition utility.h:1394
T & operator[](size_t el)
Access an element in the owning buffer.
Definition utility.h:1462
size_t size() const
Return the serialized size of the current object.
Definition utility.h:1481
T * end()
Return an iterator one past the final byte in the buffer view.
Definition utility.h:1517
buffer_t & operator=(buffer_t &&o) noexcept
Assign state from another instance while preserving ownership semantics.
Definition utility.h:1427
T * begin()
Return an iterator to the first byte in the buffer view.
Definition utility.h:1499
void fake_resize(std::size_t els)
Update the logical element count without reallocating storage.
Definition utility.h:1490
T value_type
Value type accepted by the hash functor.
Definition utility.h:682
std::size_t operator()(const value_type &value) const
Hash a value by viewing its object representation as bytes.
Definition utility.h:690
Unique pointer wrapper with customizable pointer and deleter types.
Definition utility.h:820
element_type const * const_pointer
Const pointer type exposed by the unique pointer wrapper.
Definition utility.h:833
element_type * pointer
Pointer type stored by the unique pointer wrapper.
Definition utility.h:829
const_pointer operator->() const
Access members of the managed pointer.
Definition utility.h:984
deleter_type & get_deleter()
Return the deleter used when resetting the wrapped pointer.
Definition utility.h:1020
void reset(pointer p=pointer())
Reset the object to its initial empty state.
Definition utility.h:924
pointer release()
Release the COM or platform reference owned by the pointer.
Definition utility.h:937
std::add_lvalue_reference_t< element_type const > operator*() const
Dereference the managed pointer.
Definition utility.h:966
deleter_type _deleter
Callable used to release _p.
Definition utility.h:1042
D deleter_type
Callable type used to release the managed pointer.
Definition utility.h:837
T element_type
Object type managed by the unique pointer wrapper.
Definition utility.h:825
pointer _p
Pointer currently owned by the wrapper.
Definition utility.h:1041
pointer * operator&() const
Expose the stored pointer address for C APIs that write handles.
Definition utility.h:1002
pointer get()
Return the currently wrapped value or handle.
Definition utility.h:948
Pointer wrapper that may borrow or own the pointee.
Definition utility.h:1182
element_type const & const_reference
Const reference type exposed by the pointer wrapper.
Definition utility.h:1203
const_pointer operator->() const
Access members of the wrapped pointer.
Definition utility.h:1323
element_type & reference
Mutable reference type exposed by the pointer wrapper.
Definition utility.h:1199
element_type * pointer
Mutable pointer type exposed by the pointer wrapper.
Definition utility.h:1191
const_reference operator*() const
Dereference the wrapped pointer.
Definition utility.h:1305
element_type const * const_pointer
Const pointer type exposed by the pointer wrapper.
Definition utility.h:1195
T element_type
Object type referenced by the pointer wrapper.
Definition utility.h:1187
wrap_ptr & operator=(wrap_ptr &&other) noexcept
Assign state from another instance while preserving ownership semantics.
Definition utility.h:1247
sha256_t hash(const std::string_view &plaintext)
Hashes the given plaintext using SHA-256.
Definition crypto.cpp:350
U type
Type extracted from the matched function signature.
Definition utility.h:41
T pointer
Pointer type accepted by this deleter.
Definition utility.h:1570
void operator()(pointer p)
Invoke the configured destroy function on a pointer.
Definition utility.h:1577
ReturnType(*) type(Args...)
Type extracted from the matched function signature.
Definition utility.h:1559
Definition utility.h:1352
@ little
little-endian target architecture
Definition utility.h:1693
@ big
big-endian target architecture
Definition utility.h:1697
Two-dimensional integer point.
Definition utility.h:1659
double x
X.
Definition utility.h:1660
friend std::ostream & operator<<(std::ostream &os, const point_t &p)
Operator.
Definition utility.h:1666
double y
Y.
Definition utility.h:1661
std::shared_ptr< typename P::element_type > shared_t
Shared pointer type matching a safe pointer wrapper's element type.
Definition utility.h:1165
std::string hex_vec(It begin, It end, bool rev=false)
Convert a value to a vector of hexadecimal bytes.
Definition utility.h:498
bool operator!=(const uniq_ptr< T1, D1 > &x, const uniq_ptr< T2, D2 > &y)
Compare two Sunshine unique pointers by their stored addresses.
Definition utility.h:1065
void c_free(T *p)
Release memory allocated by C APIs with free.
Definition utility.h:1601
typename __either< V, X, Y >::type either_t
Compile-time selector for one of two types.
Definition utility.h:242
bool operator==(const uniq_ptr< T1, D1 > &x, const uniq_ptr< T2, D2 > &y)
Compare two Sunshine unique pointers by their stored addresses.
Definition utility.h:1053
auto fail_guard(T &&f)
Create a scope guard that runs unless it is disabled.
Definition utility.h:314
void append_struct(std::vector< uint8_t > &buf, const T &_struct)
Append the raw bytes of a trivially-copyable structure to a byte buffer.
Definition utility.h:325
auto big(T x)
Convert a value to or from big-endian byte order.
Definition utility.h:1806
either_t<(std::is_same_v< T, bool >||is_pointer_v< T >), T, std::optional< T > > optional_t
Optional trait value used by endian serialization helpers.
Definition utility.h:1385
std::string log_hex(const T &value)
Format a value as hexadecimal text for logging.
Definition utility.h:485
std::int64_t from_chars(const char *begin, const char *end)
Convert from chars.
Definition utility.h:726
auto little(T x)
Convert a value to or from little-endian byte order.
Definition utility.h:1795
std::string from_hex_vec(const std::string &hex, bool rev=false)
Convert from hex vec.
Definition utility.h:621
T either(std::optional< T > &&l, T &&r)
Build an either value from a left-hand value.
Definition utility.h:1543
auto enm(const T &val) -> const std::underlying_type_t< T > &
Convert between enum values and their string names.
Definition utility.h:704
constexpr bool is_pointer_v
Trait value indicating whether the template argument is a pointer.
Definition utility.h:1345
T from_hex(const std::string_view &hex, bool rev=false)
Convert from hex.
Definition utility.h:559
void dynamic(T *p)
Create a non-owning dynamic buffer view over contiguous memory.
Definition utility.h:1611
Hex< T > hex(const T &elem, bool rev=false)
Serialize an element as hexadecimal text.
Definition utility.h:474
std::string_view view(It begin, It end)
Read the current value without removing it from the queue.
Definition utility.h:1641