HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
BON8.hpp
1// Copyright Take Vos 2020-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../byte_string.hpp"
8#include "../utility/module.hpp"
9#include "../datum.hpp"
10#include <cstddef>
11#include <string>
12
13hi_warning_push();
14// C26429: Symbol '' is never tested for nullness, it can be marked as not_null (f.23)
15// False positive reported: https://developercommunity.visualstudio.com/t/C26429-false-positive-on-reference-to-po/10262151
16hi_warning_ignore_msvc(26429);
17
18namespace hi::inline v1 {
19namespace detail {
20constexpr auto BON8_code_array_count0 = uint8_t{0x80};
21constexpr auto BON8_code_array_count1 = uint8_t{0x81};
22constexpr auto BON8_code_array_count2 = uint8_t{0x82};
23constexpr auto BON8_code_array_count3 = uint8_t{0x83};
24constexpr auto BON8_code_array_count4 = uint8_t{0x84};
25constexpr auto BON8_code_array = uint8_t{0x85};
26constexpr auto BON8_code_object_count0 = uint8_t{0x86};
27constexpr auto BON8_code_object_count1 = uint8_t{0x87};
28constexpr auto BON8_code_object_count2 = uint8_t{0x88};
29constexpr auto BON8_code_object_count3 = uint8_t{0x89};
30constexpr auto BON8_code_object_count4 = uint8_t{0x8a};
31constexpr auto BON8_code_object = uint8_t{0x8b};
32constexpr auto BON8_code_int32 = uint8_t{0x8c};
33constexpr auto BON8_code_int64 = uint8_t{0x8d};
34constexpr auto BON8_code_binary32 = uint8_t{0x8e};
35constexpr auto BON8_code_binary64 = uint8_t{0x8f};
36constexpr auto BON8_code_positive_s = uint8_t{0x90};
37constexpr auto BON8_code_positive_e = uint8_t{0xb7};
38constexpr auto BON8_code_negative_s = uint8_t{0xb8};
39constexpr auto BON8_code_negative_e = uint8_t{0xc1};
40
41// The last 8 code-units after the extended characters.
42constexpr auto BON8_code_bool_false = uint8_t{0xf8};
43constexpr auto BON8_code_bool_true = uint8_t{0xf9};
44constexpr auto BON8_code_null = uint8_t{0xfa};
45constexpr auto BON8_code_float_min_one = uint8_t{0xfb};
46constexpr auto BON8_code_float_zero = uint8_t{0xfc};
47constexpr auto BON8_code_float_one = uint8_t{0xfd};
48constexpr auto BON8_code_eoc = uint8_t{0xfe};
49constexpr auto BON8_code_eot = uint8_t{0xff};
50
57[[nodiscard]] datum decode_BON8(cbyteptr& ptr, cbyteptr last);
58
59[[nodiscard]] bstring encode_BON8(datum const& value);
60
64 bool open_string;
65 bstring output;
66
67public:
68 BON8_encoder() noexcept : open_string(false), output() {}
69
72 bstring const& get() noexcept
73 {
74 if (open_string) {
75 output += static_cast<std::byte>(BON8_code_eot);
76 open_string = false;
77 }
78 return output;
79 }
80
84 void add(signed long long value) noexcept
85 {
86 open_string = false;
87
89 output += static_cast<std::byte>(BON8_code_int64);
90 for (int i = 0; i != 8; ++i) {
91 output += static_cast<std::byte>(value >> (56 - i * 8));
92 }
93
94 } else if (value <= -33818507) {
95 output += static_cast<std::byte>(BON8_code_int32);
96 for (int i = 0; i != 4; ++i) {
97 output += static_cast<std::byte>(value >> (24 - i * 8));
98 }
99
100 } else if (value <= -264075) {
101 value = -(value + 264075);
102 output += static_cast<std::byte>(0xf0 + (value >> 22 & 0x07));
103 output += static_cast<std::byte>(0xc0 + (value >> 16 & 0x3f));
104 output += static_cast<std::byte>(value >> 8);
105 output += static_cast<std::byte>(value);
106
107 } else if (value <= -1931) {
108 value = -(value + 1931);
109 output += static_cast<std::byte>(0xe0 + (value >> 14 & 0x0f));
110 output += static_cast<std::byte>(0xc0 + (value >> 8 & 0x3f));
111 output += static_cast<std::byte>(value);
112
113 } else if (value <= -11) {
114 value = -(value + 11);
115 output += static_cast<std::byte>(0xc2 + (value >> 6 & 0x1f));
116 output += static_cast<std::byte>(0xc0 + (value & 0x3f));
117
118 } else if (value <= -1) {
119 value = -(value + 1);
120 output += static_cast<std::byte>(BON8_code_negative_s + value);
121
122 } else if (value <= 39) {
123 output += static_cast<std::byte>(BON8_code_positive_s + value);
124
125 } else if (value <= 3879) {
126 value -= 40;
127 output += static_cast<std::byte>(0xc2 + (value >> 7 & 0x1f));
128 output += static_cast<std::byte>(value & 0x7f);
129
130 } else if (value <= 528167) {
131 value -= 3880;
132 output += static_cast<std::byte>(0xe0 + (value >> 15 & 0x0f));
133 output += static_cast<std::byte>(value >> 8 & 0x7f);
134 output += static_cast<std::byte>(value);
135
136 } else if (value <= 67637031) {
137 value -= 528168;
138 output += static_cast<std::byte>(0xf0 + (value >> 23 & 0x17));
139 output += static_cast<std::byte>(value >> 16 & 0x7f);
140 output += static_cast<std::byte>(value >> 8);
141 output += static_cast<std::byte>(value);
142
143 } else if (value <= std::numeric_limits<int32_t>::max()) {
144 output += static_cast<std::byte>(BON8_code_int32);
145 for (int i = 0; i != 4; ++i) {
146 output += static_cast<std::byte>(value >> (24 - i * 8));
147 }
148
149 } else {
150 output += static_cast<std::byte>(BON8_code_int64);
151 for (int i = 0; i != 8; ++i) {
152 output += static_cast<std::byte>(value >> (56 - i * 8));
153 }
154 }
155 }
156
160 void add(unsigned long long value) noexcept
161 {
162 return add(narrow_cast<signed long long>(value));
163 }
164
168 void add(signed long value) noexcept
169 {
170 return add(narrow_cast<signed long long>(value));
171 }
172
176 void add(unsigned long value) noexcept
177 {
178 return add(narrow_cast<signed long long>(value));
179 }
180
184 void add(signed int value) noexcept
185 {
186 return add(narrow_cast<signed long long>(value));
187 }
188
192 void add(unsigned int value) noexcept
193 {
194 return add(narrow_cast<signed long long>(value));
195 }
196
200 void add(signed short value) noexcept
201 {
202 return add(narrow_cast<signed long long>(value));
203 }
204
208 void add(unsigned short value) noexcept
209 {
210 return add(narrow_cast<signed long long>(value));
211 }
212
216 void add(signed char value) noexcept
217 {
218 return add(narrow_cast<signed long long>(value));
219 }
220
224 void add(unsigned char value) noexcept
225 {
226 return add(narrow_cast<signed long long>(value));
227 }
228
232 void add(double value) noexcept
233 {
234 open_string = false;
235
236 hilet f32 = static_cast<float>(value);
237 hilet f32_64 = static_cast<double>(f32);
238
239 if (value == -1.0) {
240 output += static_cast<std::byte>(BON8_code_float_min_one);
241
242 } else if (value == 0.0 and not std::signbit(value)) {
243 output += static_cast<std::byte>(BON8_code_float_zero);
244
245 } else if (value == 1.0) {
246 output += static_cast<std::byte>(BON8_code_float_one);
247
248 } else if (f32_64 == value) {
249 // After conversion to 32-bit float, precession was not reduced.
250 uint32_t u32;
251 std::memcpy(&u32, &f32, sizeof(u32));
252
253 output += static_cast<std::byte>(BON8_code_binary32);
254 for (int i = 0; i != 4; ++i) {
255 output += static_cast<std::byte>(u32 >> (24 - i * 8));
256 }
257
258 } else {
259 uint64_t u64;
260 std::memcpy(&u64, &value, sizeof(u64));
261
262 output += static_cast<std::byte>(BON8_code_binary64);
263 for (int i = 0; i != 8; ++i) {
264 output += static_cast<std::byte>(u64 >> (56 - i * 8));
265 }
266 }
267 }
268
272 void add(float value) noexcept
273 {
274 return add(static_cast<double>(value));
275 }
276
280 void add(bool value) noexcept
281 {
282 open_string = false;
283 output += static_cast<std::byte>(value ? BON8_code_bool_true : BON8_code_bool_false);
284 }
285
289 void add(nullptr_t value) noexcept
290 {
291 open_string = false;
292 output += static_cast<std::byte>(BON8_code_null);
293 }
294
300 void add(std::string_view value) noexcept
301 {
302 if (open_string) {
303 output += static_cast<std::byte>(BON8_code_eot);
304 }
305
306 if (value.empty()) {
307 output += static_cast<std::byte>(BON8_code_eot);
308 open_string = false;
309
310 } else {
311 int multi_byte = 0;
312
313 for (hilet _c : value) {
314 hilet c = truncate<uint8_t>(_c);
315
316#ifndef NDEBUG
317 if (multi_byte == 0) {
318 if (c >= 0xc2 and c <= 0xdf) {
319 multi_byte = 1;
320 } else if (c >= 0xe0 and c <= 0xef) {
321 multi_byte = 2;
322 } else if (c >= 0xf0 and c <= 0xf7) {
323 multi_byte = 3;
324 } else {
325 hi_assert(c <= 0x7f);
326 }
327
328 } else {
329 hi_assert(c >= 0x80 and c <= 0xbf);
330 --multi_byte;
331 }
332#endif
333
334 output += static_cast<std::byte>(c);
335 }
336 hi_assert(multi_byte == 0);
337
338 open_string = true;
339 }
340 }
341
347 void add(std::string const& value) noexcept
348 {
349 add(std::string_view{value});
350 }
351
357 void add(char const *value) noexcept
358 {
359 add(std::string_view{value});
360 }
361
365 void add(datum const& value);
366
371 template<typename T>
372 void add(std::vector<T> const& items)
373 {
374 open_string = false;
375 if (size(items) <= 4) {
376 output += static_cast<std::byte>(BON8_code_array_count0 + size(items));
377 } else {
378 output += static_cast<std::byte>(BON8_code_array);
379 }
380
381 for (hilet& item : items) {
382 add(item);
383 }
384
385 if (size(items) > 4) {
386 output += static_cast<std::byte>(BON8_code_eoc);
387 open_string = false;
388 }
389 }
390
396 template<typename Key, typename Value>
397 void add(std::map<Key, Value> const& items)
398 {
399 using key_type = typename std::remove_cvref_t<decltype(items)>::key_type;
400
401 open_string = false;
402 if (size(items) <= 4) {
403 output += static_cast<std::byte>(BON8_code_object_count0 + size(items));
404 } else {
405 output += static_cast<std::byte>(BON8_code_object);
406 }
407
408 for (hilet& item : items) {
409 if (auto *s = get_if<std::string>(item.first)) {
410 add(*s);
411 } else {
412 throw operation_error("BON8 object keys must be strings");
413 }
414 add(item.second);
415 }
416
417 if (size(items) > 4) {
418 output += static_cast<std::byte>(BON8_code_eoc);
419 open_string = false;
420 }
421 }
422};
423
424void BON8_encoder::add(datum const& value)
425{
426 if (auto s = get_if<std::string>(value)) {
427 add(*s);
428 } else if (auto b = get_if<bool>(value)) {
429 add(*b);
430 } else if (holds_alternative<nullptr_t>(value)) {
431 add(nullptr);
432 } else if (auto i = get_if<long long>(value)) {
433 add(*i);
434 } else if (auto f = get_if<double>(value)) {
435 add(*f);
436 } else if (auto v = get_if<datum::vector_type>(value)) {
437 add(*v);
438 } else if (auto m = get_if<datum::map_type>(value)) {
439 add(*m);
440 } else {
441 throw operation_error("Datum value can not be encoded to BON8");
442 }
443}
444
453[[nodiscard]] int BON8_multibyte_count(cbyteptr ptr, cbyteptr last)
454{
456 hi_assert_not_null(last);
457
458 hilet c0 = static_cast<uint8_t>(*ptr);
459 hilet count = c0 <= 0xdf ? 2 : c0 <= 0xef ? 3 : 4;
460
461 hi_check(ptr + count <= last, "Incomplete Multi-byte character at end of buffer");
462
463 hilet c1 = static_cast<uint8_t>(*(ptr + 1));
464 return (c1 < 0x80 or c1 > 0xbf) ? -count : count;
465}
466
475[[nodiscard]] datum decode_BON8_int(cbyteptr& ptr, cbyteptr last, int count)
476{
478 hi_assert_not_null(last);
479 hi_assert(count == 4 || count == 8);
480
481 auto u64 = uint64_t{0};
482 for (int i = 0; i != count; ++i) {
483 hi_check(ptr != last, "Incomplete signed integer at end of buffer");
484 u64 <<= 8;
485 u64 |= static_cast<uint64_t>(*(ptr++));
486 }
487
488 if (count == 4) {
489 hilet u32 = truncate<uint32_t>(u64);
490 hilet i32 = truncate<int32_t>(u32);
491 return datum{i32};
492 } else {
493 hilet i64 = truncate<int64_t>(u64);
494 return datum{i64};
495 }
496}
497
498[[nodiscard]] datum decode_BON8_float(cbyteptr& ptr, cbyteptr last, int count)
499{
501 hi_assert_not_null(last);
502 hi_assert(count == 4 || count == 8);
503
504 auto u64 = uint64_t{0};
505 for (int i = 0; i != count; ++i) {
506 hi_check(ptr != last, "Incomplete signed integer at end of buffer");
507 u64 <<= 8;
508 u64 |= static_cast<uint64_t>(*(ptr++));
509 }
510
511 if (count == 4) {
512 hilet u32 = truncate<uint32_t>(u64);
513 float f32;
514 std::memcpy(&f32, &u32, sizeof(f32));
515 return datum{f32};
516
517 } else {
518 double f64;
519 std::memcpy(&f64, &u64, sizeof(f64));
520 return datum{f64};
521 }
522}
523
524[[nodiscard]] datum decode_BON8_array(cbyteptr& ptr, cbyteptr last)
525{
527 hi_assert_not_null(last);
528
529 auto r = datum::make_vector();
530 auto& vector = get<datum::vector_type>(r);
531
532 while (ptr != last) {
533 if (*ptr == static_cast<std::byte>(BON8_code_eoc)) {
534 ++ptr;
535 return r;
536
537 } else {
538 vector.push_back(decode_BON8(ptr, last));
539 }
540 }
541 throw parse_error("Incomplete array at end of buffer");
542}
543
544[[nodiscard]] datum decode_BON8_array(cbyteptr& ptr, cbyteptr last, std::size_t count)
545{
546 auto r = datum::make_vector();
547 auto& vector = get<datum::vector_type>(r);
548
549 while (count--) {
550 vector.push_back(decode_BON8(ptr, last));
551 }
552 return r;
553}
554
555[[nodiscard]] datum decode_BON8_object(cbyteptr& ptr, cbyteptr last)
556{
558 hi_assert_not_null(last);
559
560 auto r = datum::make_map();
561 auto& map = get<datum::map_type>(r);
562
563 while (ptr != last) {
564 if (*ptr == static_cast<std::byte>(BON8_code_eoc)) {
565 ++ptr;
566 return r;
567
568 } else {
569 auto key = decode_BON8(ptr, last);
570 hi_check(holds_alternative<std::string>(key), "Key in object is not a string");
571
572 auto value = decode_BON8(ptr, last);
573 map.emplace(std::move(key), std::move(value));
574 }
575 }
576 throw parse_error("Incomplete object at end of buffer");
577}
578
579[[nodiscard]] datum decode_BON8_object(cbyteptr& ptr, cbyteptr last, std::size_t count)
580{
581 auto r = datum::make_map();
582 auto& map = get<datum::map_type>(r);
583
584 while (count--) {
585 auto key = decode_BON8(ptr, last);
586 hi_check(holds_alternative<std::string>(key), "Key in object is not a string");
587
588 auto value = decode_BON8(ptr, last);
589 map.emplace(std::move(key), std::move(value));
590 }
591 return r;
592}
593
594[[nodiscard]] long long decode_BON8_UTF8_like_int(cbyteptr& ptr, cbyteptr last, int count) noexcept
595{
597 hi_assert_not_null(last);
598 hi_assert(count >= 2 && count <= 4);
599 hi_assert(ptr != last);
600 hilet c0 = static_cast<uint8_t>(*(ptr++));
601
602 hilet mask = uint8_t{0b0111'1111} >> count;
603 auto value = static_cast<long long>(c0 & mask);
604 if (count == 2) {
605 // The two byte sequence starts with 0xc2, leaving only 30 entries in the first byte.
606 value -= 2;
607 }
608
609 // The second byte determines the sign, and adds 6 or 7 bits to the number.
610 hi_assert(ptr != last);
611 hilet c1 = static_cast<uint8_t>(*(ptr++));
612 hilet is_positive = c1 <= 0x7f;
613 if (is_positive) {
614 value <<= 7;
615 value |= static_cast<long long>(c1);
616 } else {
617 value <<= 6;
618 value |= static_cast<long long>(c1 & 0b0011'1111);
619 }
620
621 switch (count) {
622 case 4:
623 hi_assert(ptr != last);
624 value <<= 8;
625 value |= static_cast<int>(*(ptr++));
626 [[fallthrough]];
627 case 3:
628 hi_assert(ptr != last);
629 value <<= 8;
630 value |= static_cast<int>(*(ptr++));
631 [[fallthrough]];
632 default:;
633 }
634
635 if (is_positive) {
636 switch (count) {
637 case 2:
638 return value + 40;
639 case 3:
640 return value + 3880;
641 case 4:
642 return value + 528168;
643 default:
645 }
646
647 } else {
648 switch (count) {
649 case 2:
650 return -(value + 11);
651 case 3:
652 return -(value + 1931);
653 case 4:
654 return -(value + 264075);
655 default:
657 }
658 }
659}
660
661[[nodiscard]] datum decode_BON8(cbyteptr& ptr, cbyteptr last)
662{
664 hi_assert_not_null(last);
665
666 std::string str;
667
668 while (ptr != last) {
669 hilet c = static_cast<uint8_t>(*ptr);
670
671 if (c == BON8_code_eot) {
672 // End of string found, return the current string.
673 ++ptr;
674 return datum{str};
675
676 } else if (c <= 0x7f) {
677 // ASCII character.
678 str += static_cast<char>(*(ptr++));
679 continue;
680
681 } else if (c >= 0xc2 && c <= 0xf7) {
682 hilet count = BON8_multibyte_count(ptr, last);
683 if (count > 0) {
684 // Multibyte UTF-8 code-point, The count includes the first code-unit.
685 for (int i = 0; i != count; ++i) {
686 str += static_cast<char>(*(ptr++));
687 }
688 continue;
689
690 } else if (not str.empty()) {
691 // Multibyte integer found, but first return the current string.
692 return datum{str};
693
694 } else {
695 // Multibyte integer, the first code-unit includes part of the integer.
696 return datum{decode_BON8_UTF8_like_int(ptr, last, -count)};
697 }
698
699 } else if (not str.empty()) {
700 // This must be a non-string type, but first return the current string.
701 return datum{str};
702
703 } else {
704 // This is one of the non-string types.
705 ++ptr;
706 switch (c) {
707 case BON8_code_null:
708 return datum{nullptr};
709 case BON8_code_bool_false:
710 return datum{false};
711 case BON8_code_bool_true:
712 return datum{true};
713 case BON8_code_float_min_one:
714 return datum{-1.0f};
715 case BON8_code_float_zero:
716 return datum{0.0f};
717 case BON8_code_float_one:
718 return datum{1.0f};
719 case BON8_code_int32:
720 return decode_BON8_int(ptr, last, 4);
721 case BON8_code_int64:
722 return decode_BON8_int(ptr, last, 8);
723 case BON8_code_binary32:
724 return decode_BON8_float(ptr, last, 4);
725 case BON8_code_binary64:
726 return decode_BON8_float(ptr, last, 8);
727 case BON8_code_array_count0:
728 return datum::make_vector();
729 case BON8_code_array_count1:
730 return decode_BON8_array(ptr, last, 1);
731 case BON8_code_array_count2:
732 return decode_BON8_array(ptr, last, 2);
733 case BON8_code_array_count3:
734 return decode_BON8_array(ptr, last, 3);
735 case BON8_code_array_count4:
736 return decode_BON8_array(ptr, last, 4);
737 case BON8_code_array:
738 return decode_BON8_array(ptr, last);
739 case BON8_code_object_count0:
740 return datum::make_map();
741 case BON8_code_object_count1:
742 return decode_BON8_object(ptr, last, 1);
743 case BON8_code_object_count2:
744 return decode_BON8_object(ptr, last, 2);
745 case BON8_code_object_count3:
746 return decode_BON8_object(ptr, last, 3);
747 case BON8_code_object_count4:
748 return decode_BON8_object(ptr, last, 4);
749 case BON8_code_object:
750 return decode_BON8_object(ptr, last);
751 case BON8_code_eoc:
752 throw parse_error("Unexpected end-of-container");
753 case BON8_code_eot:
754 throw parse_error("Unexpected end-of-text");
755 default:
756 // Everything below this, are non-string types.
757 if (c >= BON8_code_positive_s and c <= BON8_code_positive_e) {
758 return datum{c - BON8_code_positive_s};
759
760 } else if (c >= BON8_code_negative_s and c <= BON8_code_negative_e) {
761 return datum{~truncate<int>(c - BON8_code_negative_s)};
762
763 } else {
765 }
766 }
767 }
768 }
769 throw parse_error("Unexpected end-of-buffer");
770}
771} // namespace detail
772
777[[nodiscard]] datum decode_BON8(std::span<const std::byte> buffer)
778{
779 auto *ptr = buffer.data();
780 auto *last = ptr + buffer.size();
781 return detail::decode_BON8(ptr, last);
782}
783
788[[nodiscard]] datum decode_BON8(bstring const& buffer)
789{
790 auto *ptr = buffer.data();
791 auto *last = ptr + buffer.size();
792 return detail::decode_BON8(ptr, last);
793}
794
799[[nodiscard]] datum decode_BON8(bstring_view buffer)
800{
801 auto *ptr = buffer.data();
802 auto *last = ptr + buffer.size();
803 return detail::decode_BON8(ptr, last);
804}
805
810[[nodiscard]] bstring encode_BON8(datum const& value)
811{
812 auto encoder = detail::BON8_encoder{};
813 encoder.add(value);
814 return encoder.get();
815}
816
817} // namespace hi::inline v1
818
819hi_warning_pop();
#define hi_check(expression, message,...)
Check if the expression is valid, or throw a parse_error.
Definition assert.hpp:95
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:184
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:264
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:223
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
@ m
Mirror but not bracket.
BON8 encoder.
Definition BON8.hpp:63
void add(std::string const &value) noexcept
Add a UTF-8 string.
Definition BON8.hpp:347
void add(double value) noexcept
Add a floating point number.
Definition BON8.hpp:232
void add(float value) noexcept
Add a floating point number.
Definition BON8.hpp:272
void add(unsigned long long value) noexcept
And a unsigned integer.
Definition BON8.hpp:160
void add(nullptr_t value) noexcept
Add a null.
Definition BON8.hpp:289
void add(bool value) noexcept
Add a boolean.
Definition BON8.hpp:280
void add(signed long value) noexcept
And a signed integer.
Definition BON8.hpp:168
void add(signed int value) noexcept
And a signed integer.
Definition BON8.hpp:184
void add(signed short value) noexcept
And a signed integer.
Definition BON8.hpp:200
void add(std::vector< T > const &items)
Add a vector of values of the same type.
Definition BON8.hpp:372
void add(unsigned int value) noexcept
And a unsigned integer.
Definition BON8.hpp:192
void add(unsigned long value) noexcept
And a unsigned integer.
Definition BON8.hpp:176
void add(char const *value) noexcept
Add a UTF-8 string.
Definition BON8.hpp:357
void add(signed char value) noexcept
And a signed integer.
Definition BON8.hpp:216
void add(signed long long value) noexcept
And a signed integer.
Definition BON8.hpp:84
bstring const & get() noexcept
Return a byte_string of the encoded object.
Definition BON8.hpp:72
void add(unsigned short value) noexcept
And a unsigned integer.
Definition BON8.hpp:208
void add(unsigned char value) noexcept
And a unsigned integer.
Definition BON8.hpp:224
void add(std::string_view value) noexcept
Add a UTF-8 string.
Definition BON8.hpp:300
void add(std::map< Key, Value > const &items)
Add a map of key/values pairs.
Definition BON8.hpp:397
A dynamic data type.
Definition datum.hpp:219
T count(T... args)
T data(T... args)
T empty(T... args)
T memcpy(T... args)
T move(T... args)
T signbit(T... args)
T size(T... args)