131 static constexpr uint64_t
make_string(std::string_view str)
133 ttlet len = str.size();
140 for (uint64_t i = 0; i < len; i++) {
144 return (string_mask + (len << 40)) | x;
153 static uint64_t make_pointer(uint64_t mask,
void *ptr)
155 return mask | (
reinterpret_cast<uint64_t
>(ptr) & pointer_mask);
163 static constexpr uint64_t id_to_mask(uint64_t
id)
176 static constexpr uint16_t make_id(uint16_t
id)
178 return ((
id & 0x10) << 11) | (
id & 0xf) | 0x7ff0;
182 static constexpr int64_t minimum_int = 0xffff'8000'0000'0000LL;
184 static constexpr int64_t maximum_int = 0x0000'7fff'ffff'ffffLL;
186 static constexpr int64_t minimum_mantissa = 0xffff'ff80'0000'0000LL;
187 static constexpr int64_t maximum_mantissa = 0x0000'007f'ffff'ffffLL;
189 static constexpr uint16_t exponent_mask = 0b0111'1111'1111'0000;
190 static constexpr uint64_t pointer_mask = 0x0000'ffff'ffff'ffff;
192 static constexpr uint64_t small_undefined = 0;
193 static constexpr uint64_t small_null = 1;
194 static constexpr uint64_t small_true = 2;
195 static constexpr uint64_t small_false = 3;
196 static constexpr uint64_t small_break = 4;
197 static constexpr uint64_t small_continue = 5;
199 static constexpr uint16_t phy_small_id = make_id(0b00001);
200 static constexpr uint16_t phy_decimal_id = make_id(0b00010);
201 static constexpr uint16_t phy_ymd_id = make_id(0b00011);
202 static constexpr uint16_t phy_integer_id = make_id(0b00100);
203 static constexpr uint16_t phy_string_id = make_id(0b00101);
204 static constexpr uint16_t phy_reserved_id0 = make_id(0b00110);
205 static constexpr uint16_t phy_reserved_id1 = make_id(0b00111);
206 static constexpr uint16_t phy_reserved_id2 = make_id(0b01000);
207 static constexpr uint16_t phy_reserved_id3 = make_id(0b01001);
208 static constexpr uint16_t phy_reserved_id4 = make_id(0b01010);
209 static constexpr uint16_t phy_reserved_id5 = make_id(0b01011);
210 static constexpr uint16_t phy_reserved_id6 = make_id(0b01100);
211 static constexpr uint16_t phy_reserved_id7 = make_id(0b01101);
212 static constexpr uint16_t phy_reserved_id8 = make_id(0b01110);
213 static constexpr uint16_t phy_reserved_id9 = make_id(0b01111);
215 static constexpr uint16_t phy_string_ptr_id = make_id(0b10001);
216 static constexpr uint16_t phy_url_ptr_id = make_id(0b10010);
217 static constexpr uint16_t phy_integer_ptr_id = make_id(0b10011);
218 static constexpr uint16_t phy_vector_ptr_id = make_id(0b10100);
219 static constexpr uint16_t phy_map_ptr_id = make_id(0b10101);
220 static constexpr uint16_t phy_decimal_ptr_id = make_id(0b10110);
221 static constexpr uint16_t phy_bytes_ptr_id = make_id(0b10111);
222 static constexpr uint16_t phy_reserved_ptr_id0 = make_id(0b11000);
223 static constexpr uint16_t phy_reserved_ptr_id1 = make_id(0b11001);
224 static constexpr uint16_t phy_reserved_ptr_id2 = make_id(0b11010);
225 static constexpr uint16_t phy_reserved_ptr_id3 = make_id(0b11011);
226 static constexpr uint16_t phy_reserved_ptr_id4 = make_id(0b11100);
227 static constexpr uint16_t phy_reserved_ptr_id5 = make_id(0b11101);
228 static constexpr uint16_t phy_reserved_ptr_id6 = make_id(0b11110);
229 static constexpr uint16_t phy_reserved_ptr_id7 = make_id(0b11111);
231 static constexpr uint64_t small_mask = id_to_mask(phy_small_id);
232 static constexpr uint64_t undefined_mask = small_mask | small_undefined;
233 static constexpr uint64_t null_mask = small_mask | small_null;
234 static constexpr uint64_t true_mask = small_mask | small_true;
235 static constexpr uint64_t false_mask = small_mask | small_false;
236 static constexpr uint64_t break_mask = small_mask | small_break;
237 static constexpr uint64_t continue_mask = small_mask | small_continue;
238 static constexpr uint64_t string_mask = id_to_mask(phy_string_id);
239 static constexpr uint64_t integer_mask = id_to_mask(phy_integer_id);
240 static constexpr uint64_t decimal_mask = id_to_mask(phy_decimal_id);
241 static constexpr uint64_t ymd_mask = id_to_mask(phy_ymd_id);
242 static constexpr uint64_t string_ptr_mask = id_to_mask(phy_string_ptr_id);
243 static constexpr uint64_t url_ptr_mask = id_to_mask(phy_url_ptr_id);
244 static constexpr uint64_t integer_ptr_mask = id_to_mask(phy_integer_ptr_id);
245 static constexpr uint64_t vector_ptr_mask = id_to_mask(phy_vector_ptr_id);
246 static constexpr uint64_t map_ptr_mask = id_to_mask(phy_map_ptr_id);
247 static constexpr uint64_t decimal_ptr_mask = id_to_mask(phy_decimal_ptr_id);
248 static constexpr uint64_t bytes_ptr_mask = id_to_mask(phy_bytes_ptr_id);
263 uint16_t type_id()
const noexcept
267 return static_cast<uint16_t
>(data >> 48);
270 bool is_phy_float()
const noexcept
272 ttlet
id = type_id();
273 return (
id & 0x7ff0) != 0x7ff0 || (
id & 0x000f) == 0;
276 bool is_phy_integer()
const noexcept
278 return type_id() == phy_integer_id;
281 bool is_phy_string()
const noexcept
283 return type_id() == phy_string_id;
286 bool is_phy_decimal()
const noexcept
288 return type_id() == phy_decimal_id;
291 bool is_phy_ymd()
const noexcept
293 return type_id() == phy_ymd_id;
296 bool is_phy_small()
const noexcept
298 return type_id() == phy_small_id;
301 bool is_phy_pointer()
const noexcept
303 return HasLargeObjects && (type_id() & 0xfff0) == 0xfff0;
306 bool is_phy_string_ptr()
const noexcept
308 return HasLargeObjects && type_id() == phy_string_ptr_id;
311 bool is_phy_url_ptr()
const noexcept
313 return HasLargeObjects && type_id() == phy_url_ptr_id;
316 bool is_phy_integer_ptr()
const noexcept
318 return HasLargeObjects && type_id() == phy_integer_ptr_id;
321 bool is_phy_vector_ptr()
const noexcept
323 return HasLargeObjects && type_id() == phy_vector_ptr_id;
326 bool is_phy_map_ptr()
const noexcept
328 return HasLargeObjects && type_id() == phy_map_ptr_id;
331 bool is_phy_decimal_ptr()
const noexcept
333 return HasLargeObjects && type_id() == phy_decimal_ptr_id;
336 bool is_phy_bytes_ptr()
const noexcept
338 return HasLargeObjects && type_id() == phy_bytes_ptr_id;
343 uint64_t get_unsigned_integer()
const noexcept
345 return (u64 << 16) >> 16;
350 int64_t get_signed_integer()
const noexcept
352 return static_cast<int64_t
>(u64 << 16) >> 16;
360 O *get_pointer()
const
362 return std::launder(
reinterpret_cast<O *
>(get_signed_integer()));
368 void delete_pointer()
noexcept
370 if constexpr (HasLargeObjects) {
372 case phy_integer_ptr_id:
delete get_pointer<int64_t>();
break;
373 case phy_string_ptr_id:
delete get_pointer<std::string>();
break;
374 case phy_url_ptr_id:
delete get_pointer<URL>();
break;
375 case phy_vector_ptr_id:
delete get_pointer<datum_impl::vector>();
break;
376 case phy_map_ptr_id:
delete get_pointer<datum_impl::map>();
break;
377 case phy_decimal_ptr_id:
delete get_pointer<decimal>();
break;
378 case phy_bytes_ptr_id:
delete get_pointer<bstring>();
break;
379 default: tt_no_default();
389 void copy_pointer(
datum_impl const &other)
noexcept
391 if constexpr (HasLargeObjects) {
392 switch (other.type_id()) {
393 case phy_integer_ptr_id: {
394 auto *
const p =
new int64_t(*other.get_pointer<int64_t>());
395 u64 = make_pointer(integer_ptr_mask, p);
398 case phy_string_ptr_id: {
400 u64 = make_pointer(string_ptr_mask, p);
403 case phy_url_ptr_id: {
404 auto *
const p =
new URL(*other.get_pointer<
URL>());
405 u64 = make_pointer(url_ptr_mask, p);
408 case phy_vector_ptr_id: {
410 u64 = make_pointer(vector_ptr_mask, p);
413 case phy_map_ptr_id: {
415 u64 = make_pointer(map_ptr_mask, p);
418 case phy_decimal_ptr_id: {
420 u64 = make_pointer(decimal_ptr_mask, p);
423 case phy_bytes_ptr_id: {
425 u64 = make_pointer(bytes_ptr_mask, p);
428 default: tt_no_default();
445 datum_impl() noexcept : u64(undefined_mask) {}
449 if (is_phy_pointer()) {
450 [[unlikely]] delete_pointer();
454 datum_impl(datum_impl
const &other)
noexcept
456 tt_axiom(&other !=
this);
457 if (other.is_phy_pointer()) {
458 [[unlikely]] copy_pointer(other);
466 datum_impl &operator=(datum_impl
const &other)
noexcept
468 tt_return_on_self_assignment(other);
469 if (is_phy_pointer()) {
470 [[unlikely]] delete_pointer();
473 if (other.is_phy_pointer()) {
474 [[unlikely]] copy_pointer(other);
483 datum_impl(datum_impl &&other) noexcept : u64(undefined_mask)
485 tt_axiom(&other !=
this);
488 other.u64 = undefined_mask;
491 datum_impl &operator=(datum_impl &&other)
noexcept
493 tt_return_on_self_assignment(other);
496 other.u64 = undefined_mask;
500 datum_impl(datum_impl::undefined) noexcept : u64(undefined_mask) {}
501 datum_impl(datum_impl::null) noexcept : u64(null_mask) {}
502 datum_impl(datum_impl::_break) noexcept : u64(break_mask) {}
503 datum_impl(datum_impl::_continue) noexcept : u64(continue_mask) {}
505 datum_impl(
double value) noexcept : f64(value)
507 if (value != value) {
508 u64 = undefined_mask;
511 datum_impl(
float value) noexcept : datum_impl(
static_cast<double>(value)) {}
513 datum_impl(decimal value)
noexcept
515 long long m = value.mantissa();
517 if (m < minimum_mantissa || m > maximum_mantissa) {
518 [[unlikely]]
if constexpr (HasLargeObjects)
520 auto *
const p =
new decimal(value);
521 u64 = make_pointer(decimal_ptr_mask, p);
528 int e = value.exponent();
530 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
534 datum_impl(std::chrono::year_month_day
const &ymd) noexcept :
536 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
537 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
538 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
539 0x0000ffff'ffffffff))
543 datum_impl(
unsigned long long value) noexcept : u64(integer_mask | value)
545 if (value > maximum_int) {
546 [[unlikely]]
if constexpr (HasLargeObjects)
548 auto *
const p =
new uint64_t(value);
549 u64 = make_pointer(integer_ptr_mask, p);
553 throw std::overflow_error(std::format(
"Constructing datum from integer {}, larger than {}", value, maximum_int));
557 datum_impl(
unsigned long value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
558 datum_impl(
unsigned int value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
559 datum_impl(
unsigned short value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
560 datum_impl(
unsigned char value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
562 datum_impl(
signed long long value) noexcept : u64(integer_mask | (
static_cast<uint64_t
>(value) & 0x0000ffff'ffffffff))
564 if (value < minimum_int || value > maximum_int)
567 if constexpr (HasLargeObjects) {
568 auto *
const p =
new int64_t(value);
569 u64 = make_pointer(integer_ptr_mask, p);
572 "Constructing integer {} to datum, outside {} and {}", value, minimum_int, maximum_int));
576 datum_impl(
signed long value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
577 datum_impl(
signed int value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
578 datum_impl(
signed short value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
579 datum_impl(
signed char value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
581 datum_impl(
bool value) noexcept : u64(value ? true_mask : false_mask) {}
582 datum_impl(
char value) noexcept : u64(string_mask | (uint64_t{1} << 40) | value) {}
584 datum_impl(std::string_view value) noexcept : u64(make_string(value))
587 if constexpr (HasLargeObjects) {
589 u64 = make_pointer(string_ptr_mask, p);
591 throw std::overflow_error(std::format(
"Constructing string {} to datum, larger than 6 characters", value));
596 datum_impl(
std::string const &value) noexcept : datum_impl(std::string_view(value)) {}
597 datum_impl(
char const *value) noexcept : datum_impl(std::string_view(value)) {}
599 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
600 datum_impl(URL
const &value)
noexcept
602 auto *
const p =
new URL(value);
603 u64 = make_pointer(url_ptr_mask, p);
606 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
607 datum_impl(URL &&value)
noexcept
609 auto *
const p =
new URL(
std::move(value));
610 u64 = make_pointer(url_ptr_mask, p);
613 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
614 datum_impl(datum_impl::vector
const &value)
noexcept
616 auto *
const p =
new datum_impl::vector(value);
617 u64 = make_pointer(vector_ptr_mask, p);
620 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
621 datum_impl(datum_impl::vector &&value)
noexcept
623 auto *
const p =
new datum_impl::vector(
std::move(value));
624 u64 = make_pointer(vector_ptr_mask, p);
627 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
628 datum_impl(datum_impl::map
const &value)
noexcept
630 auto *
const p =
new datum_impl::map(value);
631 u64 = make_pointer(map_ptr_mask, p);
634 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
635 datum_impl(datum_impl::map &&value)
noexcept
637 auto *
const p =
new datum_impl::map(
std::move(value));
638 u64 = make_pointer(map_ptr_mask, p);
641 datum_impl &operator=(datum_impl::undefined rhs)
noexcept
643 if (is_phy_pointer()) {
644 [[unlikely]] delete_pointer();
646 u64 = undefined_mask;
650 datum_impl &operator=(datum_impl::null rhs)
noexcept
652 if (is_phy_pointer()) {
653 [[unlikely]] delete_pointer();
659 datum_impl &operator=(datum_impl::_break rhs)
noexcept
661 if (is_phy_pointer()) {
662 [[unlikely]] delete_pointer();
668 datum_impl &operator=(datum_impl::_continue rhs)
noexcept
670 if (is_phy_pointer()) {
671 [[unlikely]] delete_pointer();
677 datum_impl &operator=(
double rhs)
noexcept
679 if (is_phy_pointer()) {
680 [[unlikely]] delete_pointer();
686 u64 = undefined_mask;
690 datum_impl &operator=(
float rhs)
noexcept
692 return *
this =
static_cast<double>(rhs);
695 datum_impl &operator=(decimal rhs)
noexcept
697 if (is_phy_pointer()) {
698 [[unlikely]] delete_pointer();
701 long long m = rhs.mantissa();
702 if (m < minimum_mantissa || m > maximum_mantissa) {
703 [[unlikely]]
if constexpr (HasLargeObjects)
705 auto *
const p =
new decimal(rhs);
706 u64 = make_pointer(decimal_ptr_mask, p);
713 int e = rhs.exponent();
715 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
720 datum_impl &operator=(std::chrono::year_month_day
const &ymd)
noexcept
722 if (is_phy_pointer()) {
723 [[unlikely]] delete_pointer();
727 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
728 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
729 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
730 0x0000ffff'ffffffff);
734 datum_impl &operator=(
unsigned long long rhs)
736 if (is_phy_pointer()) {
737 [[unlikely]] delete_pointer();
740 u64 = integer_mask |
static_cast<uint64_t
>(rhs);
741 if (rhs > maximum_int) {
742 [[unlikely]]
if constexpr (HasLargeObjects)
744 auto *
const p =
new uint64_t(rhs);
745 u64 = make_pointer(integer_ptr_mask, p);
749 throw std::overflow_error(std::format(
"Assigning integer {} to datum, larger than {}", rhs, maximum_int));
754 datum_impl &operator=(
unsigned long rhs)
noexcept
756 return *
this =
static_cast<unsigned long long>(rhs);
758 datum_impl &operator=(
unsigned int rhs)
noexcept
760 return *
this =
static_cast<unsigned long long>(rhs);
762 datum_impl &operator=(
unsigned short rhs)
noexcept
764 return *
this =
static_cast<unsigned long long>(rhs);
766 datum_impl &operator=(
unsigned char rhs)
noexcept
768 return *
this =
static_cast<unsigned long long>(rhs);
771 datum_impl &operator=(
signed long long rhs)
noexcept
773 if (is_phy_pointer()) {
774 [[unlikely]] delete_pointer();
777 u64 = integer_mask | (
static_cast<uint64_t
>(rhs) & 0x0000ffff'ffffffff);
778 if (rhs < minimum_int || rhs > maximum_int) {
779 [[unlikely]]
if constexpr (HasLargeObjects)
781 auto *
const p =
new int64_t(rhs);
782 u64 = make_pointer(integer_ptr_mask, p);
786 throw std::overflow_error(std::format(
"Assigning integer {} to datum, outside {} and {}", rhs, minimum_int, maximum_int));
792 datum_impl &operator=(
signed long rhs)
noexcept
794 return *
this =
static_cast<signed long long>(rhs);
796 datum_impl &operator=(
signed int rhs)
noexcept
798 return *
this =
static_cast<signed long long>(rhs);
800 datum_impl &operator=(
signed short rhs)
noexcept
802 return *
this =
static_cast<signed long long>(rhs);
804 datum_impl &operator=(
signed char rhs)
noexcept
806 return *
this =
static_cast<signed long long>(rhs);
809 datum_impl &operator=(
bool rhs)
noexcept
811 if (is_phy_pointer()) {
812 [[unlikely]] delete_pointer();
814 u64 = rhs ? true_mask : false_mask;
818 datum_impl &operator=(
char rhs)
noexcept
820 if (is_phy_pointer()) {
821 [[unlikely]] delete_pointer();
823 u64 = string_mask | (uint64_t{1} << 40) |
static_cast<uint64_t
>(rhs);
827 datum_impl &operator=(std::string_view rhs)
829 if (is_phy_pointer()) {
830 [[unlikely]] delete_pointer();
833 u64 = make_string(rhs);
835 if constexpr (HasLargeObjects) {
837 u64 = make_pointer(string_ptr_mask, p);
839 throw std::overflow_error(std::format(
"Assigning string {} to datum, larger than 6 characters", rhs));
847 *
this = std::string_view{rhs};
851 datum_impl &operator=(
char const *rhs)
853 *
this = std::string_view{rhs};
857 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
858 datum_impl &operator=(URL
const &rhs)
noexcept
860 if (is_phy_pointer()) {
861 [[unlikely]] delete_pointer();
864 auto *
const p =
new URL(rhs);
865 u64 = make_pointer(url_ptr_mask, p);
869 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
870 datum_impl &operator=(URL &&rhs)
noexcept
872 if (is_phy_pointer()) {
873 [[unlikely]] delete_pointer();
877 u64 = make_pointer(url_ptr_mask, p);
881 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
882 datum_impl &operator=(datum_impl::vector
const &rhs)
884 if (is_phy_pointer()) {
885 [[unlikely]] delete_pointer();
888 auto *
const p =
new datum_impl::vector(rhs);
889 u64 = make_pointer(vector_ptr_mask, p);
894 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
895 datum_impl &operator=(datum_impl::vector &&rhs)
897 if (is_phy_pointer()) {
898 [[unlikely]] delete_pointer();
901 auto *
const p =
new datum_impl::vector(
std::move(rhs));
902 u64 = make_pointer(vector_ptr_mask, p);
907 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
908 datum_impl &operator=(datum_impl::map
const &rhs)
910 if (is_phy_pointer()) {
911 [[unlikely]] delete_pointer();
914 auto *
const p =
new datum_impl::map(rhs);
915 u64 = make_pointer(map_ptr_mask, p);
920 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
921 datum_impl &operator=(datum_impl::map &&rhs)
923 if (is_phy_pointer()) {
924 [[unlikely]] delete_pointer();
927 auto *
const p =
new datum_impl::map(
std::move(rhs));
928 u64 = make_pointer(map_ptr_mask, p);
933 explicit operator double()
const
935 if (is_phy_float()) {
937 }
else if (is_decimal()) {
938 return static_cast<double>(
static_cast<decimal
>(*this));
939 }
else if (is_phy_integer()) {
940 return static_cast<double>(get_signed_integer());
941 }
else if (is_phy_integer_ptr()) {
942 return static_cast<double>(*get_pointer<int64_t>());
944 throw operation_error(
945 "Value {} of type {} can not be converted to a double", this->repr(), this->type_name());
949 explicit operator float()
const
951 return static_cast<float>(
static_cast<double>(*this));
954 explicit operator decimal()
const
956 if (is_phy_decimal()) {
957 uint64_t v = get_unsigned_integer();
958 int e =
static_cast<int8_t
>(v);
959 long long m =
static_cast<int64_t
>(v << 16) >> 24;
960 return decimal{e, m};
961 }
else if (is_phy_decimal_ptr()) {
962 return *get_pointer<decimal>();
963 }
else if (is_phy_integer() || is_phy_integer_ptr()) {
964 return decimal{
static_cast<signed long long>(*this)};
965 }
else if (is_phy_float()) {
966 return decimal{
static_cast<double>(*this)};
968 throw operation_error(
969 "Value {} of type {} can not be converted to a decimal", this->repr(), this->type_name());
973 explicit operator std::chrono::year_month_day()
const
976 ttlet u = get_unsigned_integer();
977 ttlet i = get_signed_integer();
978 ttlet day =
static_cast<unsigned>(u & 0x1f);
979 ttlet month =
static_cast<unsigned>((u >> 5) & 0xf);
980 ttlet year =
static_cast<signed>(i >> 9);
983 throw operation_error(
984 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
987 throw operation_error(
988 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
990 return std::chrono::year_month_day{std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day}};
992 throw operation_error(
993 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
997 explicit operator signed long long()
const
999 if (is_phy_integer()) {
1000 return get_signed_integer();
1001 }
else if (is_phy_integer_ptr()) {
1002 return *get_pointer<signed long long>();
1003 }
else if (is_phy_float()) {
1004 return static_cast<signed long long>(f64);
1005 }
else if (is_phy_small()) {
1006 switch (get_unsigned_integer()) {
1007 case small_true:
return 1;
1008 case small_false:
return 0;
1011 throw operation_error(
1012 "Value {} of type {} can not be converted to a signed long long", this->repr(), this->type_name());
1015 explicit operator signed long()
const
1017 ttlet v =
static_cast<signed long long>(*this);
1019 throw operation_error(
1020 "Value {} of type {} can not be converted to a signed long", this->repr(), this->type_name());
1022 return static_cast<signed long>(v);
1025 explicit operator signed int()
const
1027 ttlet v =
static_cast<signed long long>(*this);
1029 throw operation_error(
1030 "Value {} of type {} can not be converted to a signed int", this->repr(), this->type_name());
1032 return static_cast<signed int>(v);
1035 explicit operator signed short()
const
1037 ttlet v =
static_cast<signed long long>(*this);
1039 throw operation_error(
1040 "Value {} of type {} can not be converted to a signed short", this->repr(), this->type_name());
1042 return static_cast<signed short>(v);
1045 explicit operator signed char()
const
1047 ttlet v =
static_cast<int64_t
>(*this);
1049 throw operation_error(
1050 "Value {} of type {} can not be converted to a signed char", this->repr(), this->type_name());
1052 return static_cast<signed char>(v);
1055 explicit operator unsigned long long()
const
1057 ttlet v =
static_cast<signed long long>(*this);
1059 throw operation_error(
1060 "Value {} of type {} can not be converted to a unsigned long long", this->repr(), this->type_name());
1062 return static_cast<unsigned long long>(v);
1065 explicit operator unsigned long()
const
1067 ttlet v =
static_cast<unsigned long long>(*this);
1069 throw operation_error(
1070 "Value {} of type {} can not be converted to a unsigned long", this->repr(), this->type_name());
1072 return static_cast<unsigned long>(v);
1075 explicit operator unsigned int()
const
1077 ttlet v =
static_cast<unsigned long long>(*this);
1079 throw operation_error(
1080 "Value {} of type {} can not be converted to a unsigned int", this->repr(), this->type_name());
1082 return static_cast<unsigned int>(v);
1085 explicit operator unsigned short()
const
1087 ttlet v =
static_cast<unsigned long long>(*this);
1089 throw operation_error(
1090 "Value {} of type {} can not be converted to a unsigned short", this->repr(), this->type_name());
1092 return static_cast<unsigned short>(v);
1095 explicit operator unsigned char()
const
1097 ttlet v =
static_cast<unsigned long long>(*this);
1099 throw operation_error(
1100 "Value {} of type {} can not be converted to a unsigned char", this->repr(), this->type_name());
1102 return static_cast<unsigned char>(v);
1105 explicit operator bool() const noexcept
1107 switch (type_id()) {
1108 case phy_small_id:
return get_unsigned_integer() == small_true;
1109 case phy_integer_id:
return static_cast<int64_t
>(*this) != 0;
1110 case phy_decimal_id:
return static_cast<decimal
>(*this) != 0;
1111 case phy_ymd_id:
return true;
1112 case phy_integer_ptr_id:
return *get_pointer<int64_t>() != 0;
1114 case phy_string_ptr_id:
return this->size() > 0;
1115 case phy_url_ptr_id:
return true;
1116 case phy_vector_ptr_id:
return this->size() > 0;
1117 case phy_map_ptr_id:
return this->size() > 0;
1118 case phy_decimal_ptr_id:
return static_cast<decimal
>(*this) != 0;
1119 case phy_bytes_ptr_id:
return this->size() > 0;
1121 if (is_phy_float()) {
1122 return static_cast<double>(*this) != 0.0;
1129 explicit operator char()
const
1131 if (is_phy_string() && size() == 1) {
1133 }
else if (is_phy_string_ptr() && size() == 1) {
1134 return get_pointer<std::string>()->at(0);
1136 throw operation_error(
1137 "Value {} of type {} can not be converted to a char", this->repr(), this->type_name());
1141 explicit operator bstring()
const
1144 if constexpr (HasLargeObjects) {
1145 return *get_pointer<bstring>();
1150 throw operation_error(
1151 "Value {} of type {} can not be converted to bytes", this->repr(), this->type_name());
1157 switch (type_id()) {
1159 switch (get_unsigned_integer()) {
1160 case small_undefined:
return "undefined";
1161 case small_null:
return "null";
1162 case small_true:
return "true";
1163 case small_false:
return "false";
1164 case small_break:
return "break";
1165 case small_continue:
return "continue";
1166 default: tt_no_default();
1169 case phy_integer_id:
return std::format(
"{}",
static_cast<int64_t
>(*
this));
1170 case phy_decimal_id:
return std::format(
"{}",
static_cast<decimal
>(*
this));
1171 case phy_ymd_id:
return std::format(
"{}",
static_cast<std::chrono::year_month_day
>(*
this));
1172 case phy_integer_ptr_id:
1173 if constexpr (HasLargeObjects) {
1174 return std::format(
"{}",
static_cast<int64_t
>(*
this));
1179 case phy_string_id: {
1180 ttlet length = size();
1182 for (
int i = 0; i < length; i++) {
1183 buffer[i] = (u64 >> ((length - i - 1) * 8)) & 0xff;
1188 case phy_string_ptr_id:
1189 if constexpr (HasLargeObjects) {
1190 return *get_pointer<std::string>();
1195 case phy_url_ptr_id:
1196 if constexpr (HasLargeObjects) {
1197 return to_string(*get_pointer<URL>());
1202 case phy_decimal_ptr_id:
1203 if constexpr (HasLargeObjects) {
1204 return std::format(
"{}",
static_cast<decimal
>(*
this));
1209 case phy_vector_ptr_id:
1210 if constexpr (HasLargeObjects) {
1216 for (
auto i = vector_begin(); i != vector_end(); i++) {
1228 case phy_map_ptr_id:
1229 if constexpr (HasLargeObjects) {
1236 return a.first < b.first;
1244 for (
auto &item : items) {
1248 r += item.first.repr();
1250 r += item.second.repr();
1258 case phy_bytes_ptr_id:
1259 if constexpr (HasLargeObjects) {
1266 if (is_phy_float()) {
1267 auto str = std::format(
"{:g}",
static_cast<double>(*
this));
1268 if (str.find(
'.') == str.npos) {
1278 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1279 explicit operator URL()
const
1283 }
else if (is_url()) {
1284 return *get_pointer<URL>();
1286 throw operation_error(
1287 "Value {} of type {} can not be converted to a URL", this->repr(), this->type_name());
1291 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1292 explicit operator datum_impl::vector()
const
1295 return *get_pointer<datum_impl::vector>();
1297 throw operation_error(
1298 "Value {} of type {} can not be converted to a Vector", this->repr(), this->type_name());
1302 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1303 explicit operator datum_impl::map()
const
1306 return *get_pointer<datum_impl::map>();
1308 throw operation_error(
1309 "Value {} of type {} can not be converted to a Map", this->repr(), this->type_name());
1320 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1323 if (is_undefined()) {
1326 u64 = map_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1330 auto &m = *get_pointer<datum_impl::map>();
1331 auto [i, did_insert] = m.try_emplace(rhs);
1334 }
else if (is_vector() && rhs.is_integer()) {
1335 auto index =
static_cast<int64_t
>(rhs);
1336 auto &v = *get_pointer<datum_impl::vector>();
1339 index = std::ssize(v) + index;
1342 if (index < 0 || index >= std::ssize(v)) {
1344 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1350 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1361 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1365 ttlet &m = *get_pointer<datum_impl::map>();
1366 ttlet i = m.find(rhs);
1367 if (i == m.cend()) {
1368 throw operation_error(
"Could not find key {} in map of size {}", rhs.repr(), std::ssize(m));
1372 }
else if (is_vector() && rhs.is_integer()) {
1373 auto index =
static_cast<int64_t
>(rhs);
1374 ttlet &v = *get_pointer<datum_impl::vector>();
1377 index = std::ssize(v) + index;
1380 if (index < 0 || index >= std::ssize(v)) {
1382 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1388 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1400 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1404 ttlet &m = *get_pointer<datum_impl::map>();
1405 ttlet i = m.find(rhs);
1406 return i != m.cend();
1408 }
else if (is_vector() && rhs.is_integer()) {
1409 auto index =
static_cast<int64_t
>(rhs);
1410 ttlet &v = *get_pointer<datum_impl::vector>();
1413 index = std::ssize(v) + index;
1416 return index >= 0 && index < std::ssize(v);
1428 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1431 if (is_undefined()) {
1434 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1438 auto *v = get_pointer<datum_impl::vector>();
1443 throw operation_error(
"Cannot append new item onto type {}", type_name());
1447 template<
typename... Args>
1448 void emplace_back(Args &&... args)
1450 if (is_undefined()) {
1453 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1457 auto *v = get_pointer<datum_impl::vector>();
1458 v->emplace_back(std::forward<Args>(args)...);
1461 throw operation_error(
"Cannot append new item onto type {}", type_name());
1465 template<
typename Arg>
1466 void push_back(Arg &&arg)
1468 if (is_undefined()) {
1470 auto *p =
new datum_impl::vector();
1471 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1475 auto *v = get_pointer<datum_impl::vector>();
1476 v->push_back(std::forward<Arg>(arg));
1479 throw operation_error(
"Cannot append new item onto type {}", type_name());
1486 auto *v = get_pointer<datum_impl::vector>();
1490 throw operation_error(
"Cannot pop_back() onto type {}", type_name());
1494 datum_impl year()
const
1497 return {
static_cast<signed>(
static_cast<std::chrono::year_month_day
>(*this).year())};
1499 throw operation_error(
"Cannot get year() from type {}", type_name());
1503 datum_impl quarter()
const
1506 auto month =
static_cast<unsigned>(
static_cast<std::chrono::year_month_day
>(*this).month());
1507 return {((month - 1) / 3) + 1};
1509 throw operation_error(
"Cannot get month() from type {}", type_name());
1513 datum_impl month()
const
1516 return {
static_cast<unsigned>(
static_cast<std::chrono::year_month_day
>(*this).month())};
1518 throw operation_error(
"Cannot get month() from type {}", type_name());
1522 datum_impl day()
const
1525 return {
static_cast<unsigned>(
static_cast<std::chrono::year_month_day
>(*this).day())};
1527 throw operation_error(
"Cannot get day() from type {}", type_name());
1531 datum_impl
const &front()
const
1534 ttlet *v = get_pointer<datum_impl::vector>();
1538 throw operation_error(
"Cannot front() onto type {}", type_name());
1545 auto *v = get_pointer<datum_impl::vector>();
1549 throw operation_error(
"Cannot front() onto type {}", type_name());
1553 datum_impl
const &back()
const
1556 ttlet *v = get_pointer<datum_impl::vector>();
1560 throw operation_error(
"Cannot back() onto type {}", type_name());
1567 auto *v = get_pointer<datum_impl::vector>();
1571 throw operation_error(
"Cannot back() onto type {}", type_name());
1577 switch (type_id()) {
1579 switch (get_unsigned_integer()) {
1580 case small_undefined:
return "undefined";
1581 case small_null:
return "null";
1582 case small_true:
return "true";
1583 case small_false:
return "false";
1584 case small_break:
return "break";
1585 case small_continue:
return "continue";
1586 default: tt_no_default();
1588 case phy_integer_id:
1589 case phy_integer_ptr_id:
return static_cast<std::string>(*this);
1590 case phy_decimal_id:
1591 case phy_decimal_ptr_id:
return static_cast<std::string>(*this);
1592 case phy_ymd_id:
return static_cast<std::string>(*this);
1594 case phy_string_ptr_id:
return std::format(
"\"{}\"",
static_cast<std::string>(*
this));
1595 case phy_url_ptr_id:
return std::format(
"<URL {}>",
static_cast<std::string>(*
this));
1596 case phy_vector_ptr_id:
return static_cast<std::string>(*this);
1597 case phy_map_ptr_id:
return static_cast<std::string>(*this);
1598 case phy_bytes_ptr_id:
return static_cast<std::string>(*this);
1600 if (is_phy_float()) {
1615 return phy_integer_id;
1623 if (key.
size() > 0 && is_map()) {
1624 ttlet index = key.
at(0);
1625 auto &next = (*this)[index];
1627 return next.get_by_path(next_key);
1629 }
else if (key.
size() > 0 && is_vector()) {
1631 auto &
next = (*this)[index];
1633 return next.get_by_path(next_key);
1635 }
else if (key.
size() > 0) {
1636 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1644 if (key.
size() > 0 && is_map()) {
1645 ttlet index = key.
at(0);
1646 ttlet
next = (*this)[index];
1649 }
else if (key.
size() > 0 && is_vector()) {
1651 ttlet
next = (*this)[index];
1654 }
else if (key.
size() > 0) {
1655 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1661 bool is_integer() const noexcept
1663 return is_phy_integer() || is_phy_integer_ptr();
1665 bool is_decimal() const noexcept
1667 return is_phy_decimal() || is_phy_decimal_ptr();
1669 bool is_ymd() const noexcept
1671 return is_phy_ymd();
1673 bool is_float() const noexcept
1675 return is_phy_float();
1677 bool is_string() const noexcept
1679 return is_phy_string() || is_phy_string_ptr();
1681 bool is_bytes() const noexcept
1683 return is_phy_bytes_ptr();
1686 bool is_bool() const noexcept
1688 if (is_phy_small()) {
1689 ttlet tmp = get_unsigned_integer();
1690 return tmp == small_true || tmp == small_false;
1696 bool is_null() const noexcept
1698 return is_phy_small() && get_unsigned_integer() == small_null;
1701 bool is_undefined() const noexcept
1703 return is_phy_small() && get_unsigned_integer() == small_undefined;
1706 bool is_break() const noexcept
1708 return is_phy_small() && get_unsigned_integer() == small_break;
1711 bool is_continue() const noexcept
1713 return is_phy_small() && get_unsigned_integer() == small_continue;
1715 bool is_url() const noexcept
1717 return is_phy_url_ptr();
1720 bool is_vector() const noexcept
1722 return is_phy_vector_ptr();
1724 bool is_map() const noexcept
1726 return is_phy_map_ptr();
1728 bool is_numeric() const noexcept
1730 return is_integer() || is_decimal() || is_float();
1733 datum_type_t type() const noexcept
1735 switch (type_id()) {
1737 switch (get_unsigned_integer()) {
1738 case small_undefined:
return datum_type_t::Undefined;
1739 case small_null:
return datum_type_t::Null;
1740 case small_false:
return datum_type_t::Boolean;
1741 case small_true:
return datum_type_t::Boolean;
1742 case small_break:
return datum_type_t::Break;
1743 case small_continue:
return datum_type_t::Continue;
1744 default: tt_no_default();
1747 case phy_integer_id:
1748 case phy_integer_ptr_id:
return datum_type_t::Integer;
1749 case phy_decimal_id:
1750 case phy_decimal_ptr_id:
return datum_type_t::Decimal;
1751 case phy_ymd_id:
return datum_type_t::YearMonthDay;
1753 case phy_string_ptr_id:
return datum_type_t::String;
1754 case phy_url_ptr_id:
return datum_type_t::URL;
1755 case phy_vector_ptr_id:
return datum_type_t::Vector;
1756 case phy_map_ptr_id:
return datum_type_t::Map;
1757 case phy_bytes_ptr_id:
return datum_type_t::Bytes;
1759 if (is_phy_float()) {
1760 return datum_type_t::Float;
1767 char const *type_name() const noexcept
1769 switch (type_id()) {
1771 switch (get_unsigned_integer()) {
1772 case small_undefined:
return "Undefined";
1773 case small_null:
return "Null";
1774 case small_false:
return "Boolean";
1775 case small_true:
return "Boolean";
1776 case small_break:
return "Break";
1777 case small_continue:
return "Continue";
1778 default: tt_no_default();
1781 case phy_integer_id:
1782 case phy_integer_ptr_id:
return "Integer";
1783 case phy_decimal_id:
1784 case phy_decimal_ptr_id:
return "Decimal";
1785 case phy_ymd_id:
return "YearMonthDay";
1787 case phy_string_ptr_id:
return "String";
1788 case phy_url_ptr_id:
return "URL";
1789 case phy_vector_ptr_id:
return "Vector";
1790 case phy_map_ptr_id:
return "Map";
1791 case phy_bytes_ptr_id:
return "Bytes";
1793 if (is_phy_float()) {
1803 switch (type_id()) {
1804 case phy_string_id:
return (u64 >> 40) & 0xff;
1805 case phy_string_ptr_id:
return get_pointer<std::string>()->size();
1806 case phy_vector_ptr_id:
return get_pointer<datum_impl::vector>()->size();
1807 case phy_map_ptr_id:
return get_pointer<datum_impl::map>()->size();
1808 case phy_bytes_ptr_id:
return get_pointer<bstring>()->size();
1809 default:
throw operation_error(
"Can't get size of value {} of type {}.", this->repr(), this->type_name());
1813 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1814 typename map::const_iterator map_begin()
const
1816 if (is_phy_map_ptr()) {
1817 return get_pointer<datum_impl::map>()->begin();
1819 throw operation_error(
"map_begin() expect datum to be a map, but it is a {}.", this->type_name());
1823 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1824 typename map::const_iterator map_end()
const
1826 if (is_phy_map_ptr()) {
1827 return get_pointer<datum_impl::map>()->end();
1829 throw operation_error(
"map_end() expect datum to be a map, but it is a {}.", this->type_name());
1833 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1834 typename vector::const_iterator vector_begin()
const
1836 if (is_phy_vector_ptr()) {
1837 return get_pointer<datum_impl::vector>()->begin();
1839 throw operation_error(
1840 "vector_begin() expect datum to be a vector, but it is a {}.", this->type_name());
1844 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1845 typename vector::const_iterator vector_end()
const
1847 if (is_phy_vector_ptr()) {
1848 return get_pointer<datum_impl::vector>()->end();
1850 throw operation_error(
"vector_end() expect datum to be a vector, but it is a {}.", this->type_name());
1854 size_t hash() const noexcept
1856 if (is_phy_float()) {
1858 }
else if (is_phy_pointer()) {
1859 [[unlikely]]
switch (type_id())
1862 case phy_url_ptr_id:
return std::hash<URL>{}(*get_pointer<URL>());
1863 case phy_vector_ptr_id:
1864 return std::accumulate(vector_begin(), vector_end(),
size_t{0}, [](
size_t a,
auto x) {
1865 return a ^ x.hash();
1867 case phy_map_ptr_id:
1868 return std::accumulate(map_begin(), map_end(),
size_t{0}, [](
size_t a,
auto x) {
1869 return a ^ (x.first.hash() ^ x.second.hash());
1873 default: tt_no_default();
1880 datum_impl &operator++()
1882 if (!this->is_numeric()) {
1883 throw operation_error(
"Can't increment '++' value {} of type {}", this->repr(), this->type_name());
1889 datum_impl &operator--()
1891 if (!this->is_numeric()) {
1892 throw operation_error(
"Can't increment '--' value {} of type {}", this->repr(), this->type_name());
1898 datum_impl operator++(
int)
1905 datum_impl operator--(
int)
1912 datum_impl &operator+=(datum_impl
const &rhs)
1914 if (this->is_vector()) {
1915 this->push_back(rhs);
1917 *
this = *
this + rhs;
1922 datum_impl &operator-=(datum_impl
const &rhs)
1924 return *
this = *
this - rhs;
1927 datum_impl &operator*=(datum_impl
const &rhs)
1929 return *
this = *
this * rhs;
1932 datum_impl &operator/=(datum_impl
const &rhs)
1934 return *
this = *
this / rhs;
1937 datum_impl &operator%=(datum_impl
const &rhs)
1939 return *
this = *
this % rhs;
1942 datum_impl &operator<<=(datum_impl
const &rhs)
1944 return *
this = *
this << rhs;
1947 datum_impl &operator>>=(datum_impl
const &rhs)
1949 return *
this = *
this >> rhs;
1952 datum_impl &operator&=(datum_impl
const &rhs)
1954 return *
this = *
this & rhs;
1957 datum_impl &operator|=(datum_impl
const &rhs)
1959 return *
this = *
this | rhs;
1962 datum_impl &operator^=(datum_impl
const &rhs)
1964 return *
this = *
this ^ rhs;
1967 friend datum_impl operator~(datum_impl
const &rhs)
1969 if (rhs.is_integer()) {
1970 return datum_impl{~static_cast<int64_t>(rhs)};
1972 throw operation_error(
"Can't bit-wise negate '~' value {} of type {}", rhs.repr(), rhs.type_name());
1976 friend datum_impl operator-(datum_impl
const &rhs)
1978 if (rhs.is_integer()) {
1979 return datum_impl{-
static_cast<int64_t
>(rhs)};
1980 }
else if (rhs.is_decimal()) {
1981 return datum_impl{-
static_cast<decimal
>(rhs)};
1982 }
else if (rhs.is_float()) {
1983 return datum_impl{-
static_cast<double>(rhs)};
1985 throw operation_error(
"Can't arithmetic negate '-' value {} of type {}", rhs.repr(), rhs.type_name());
1989 friend datum_impl operator+(datum_impl
const &rhs)
1991 if (rhs.is_numeric()) {
1994 throw operation_error(
"Can't arithmetic posgate '+' value {} of type {}", rhs.repr(), rhs.type_name());
1998 friend bool operator==(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2000 switch (lhs.type_id()) {
2001 case datum_impl::phy_small_id:
return rhs.is_phy_small() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
2002 case datum_impl::phy_integer_id:
2003 case datum_impl::phy_integer_ptr_id:
2005 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
2006 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
2007 (rhs.is_integer() &&
static_cast<int64_t
>(lhs) ==
static_cast<int64_t
>(rhs)));
2008 case datum_impl::phy_decimal_id:
2009 case datum_impl::phy_decimal_ptr_id:
2011 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
2012 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
2013 (rhs.is_integer() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)));
2014 case datum_impl::phy_ymd_id:
return rhs.is_ymd() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
2015 case datum_impl::phy_string_id:
2016 case datum_impl::phy_string_ptr_id:
2019 (rhs.is_url() &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs)));
2020 case datum_impl::phy_url_ptr_id:
2021 return (rhs.is_url() || rhs.is_string()) &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs);
2022 case datum_impl::phy_vector_ptr_id:
2023 return rhs.is_vector() && *lhs.get_pointer<datum_impl::vector>() == *rhs.get_pointer<datum_impl::vector>();
2024 case datum_impl::phy_map_ptr_id:
2025 return rhs.is_map() && *lhs.get_pointer<datum_impl::map>() == *rhs.get_pointer<datum_impl::map>();
2026 case datum_impl::phy_bytes_ptr_id:
return (rhs.is_bytes() &&
static_cast<bstring
>(lhs) ==
static_cast<bstring
>(rhs));
2028 if (lhs.is_phy_float()) {
2029 return rhs.is_numeric() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs);
2036 friend bool operator<(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2038 switch (lhs.type_id()) {
2039 case datum_impl::phy_small_id:
2040 if (lhs.is_bool() && rhs.is_bool()) {
2041 return static_cast<bool>(lhs) <
static_cast<bool>(rhs);
2043 return lhs.get_unsigned_integer() < rhs.get_unsigned_integer();
2045 case datum_impl::phy_integer_id:
2046 case datum_impl::phy_integer_ptr_id:
2047 if (rhs.is_float()) {
2048 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2049 }
else if (rhs.is_decimal()) {
2050 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2051 }
else if (rhs.is_integer()) {
2052 return static_cast<int64_t
>(lhs) <
static_cast<int64_t
>(rhs);
2054 return lhs.type_order() < rhs.type_order();
2056 case datum_impl::phy_decimal_id:
2057 case datum_impl::phy_decimal_ptr_id:
2058 if (rhs.is_float()) {
2059 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2060 }
else if (rhs.is_decimal()) {
2061 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2062 }
else if (rhs.is_integer()) {
2063 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2065 return lhs.type_order() < rhs.type_order();
2067 case datum_impl::phy_ymd_id:
2069 return static_cast<std::chrono::year_month_day
>(lhs) <
static_cast<std::chrono::year_month_day
>(rhs);
2071 return lhs.type_order() < rhs.type_order();
2073 case datum_impl::phy_string_id:
2074 case datum_impl::phy_string_ptr_id:
2075 if (rhs.is_string()) {
2077 }
else if (rhs.is_url()) {
2078 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2080 return lhs.type_order() < rhs.type_order();
2082 case datum_impl::phy_url_ptr_id:
2083 if (rhs.is_url() || rhs.is_string()) {
2084 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2086 return lhs.type_order() < rhs.type_order();
2088 case datum_impl::phy_vector_ptr_id:
2089 if (rhs.is_vector()) {
2090 return *lhs.get_pointer<datum_impl::vector>() < *rhs.get_pointer<datum_impl::vector>();
2092 return lhs.type_order() < rhs.type_order();
2094 case datum_impl::phy_map_ptr_id:
2096 return *lhs.get_pointer<datum_impl::map>() < *rhs.get_pointer<datum_impl::map>();
2098 return lhs.type_order() < rhs.type_order();
2100 case datum_impl::phy_bytes_ptr_id:
2101 if (rhs.is_bytes()) {
2102 return static_cast<bstring
>(lhs) <
static_cast<bstring
>(rhs);
2104 return lhs.type_order() < rhs.type_order();
2107 if (lhs.is_phy_float()) {
2108 if (rhs.is_numeric()) {
2109 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2111 return lhs.type_order() < rhs.type_order();
2119 friend bool operator!=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2121 return !(lhs == rhs);
2124 friend bool operator>(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2129 friend bool operator<=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2131 return !(rhs < lhs);
2134 friend bool operator>=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2136 return !(lhs < rhs);
2139 friend datum_impl operator+(datum_impl
const &lhs, datum_impl
const &rhs)
2141 if (lhs.is_float() || rhs.is_float()) {
2142 ttlet lhs_ =
static_cast<double>(lhs);
2143 ttlet rhs_ =
static_cast<double>(rhs);
2144 return datum_impl{lhs_ + rhs_};
2146 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2147 ttlet lhs_ =
static_cast<decimal
>(lhs);
2148 ttlet rhs_ =
static_cast<decimal
>(rhs);
2149 return datum_impl{lhs_ + rhs_};
2151 }
else if (lhs.is_integer() || rhs.is_integer()) {
2152 ttlet lhs_ =
static_cast<long long int>(lhs);
2153 ttlet rhs_ =
static_cast<long long int>(rhs);
2154 return datum_impl{lhs_ + rhs_};
2156 }
else if (lhs.is_string() && rhs.is_string()) {
2159 return datum_impl{
std::move(lhs_ + rhs_)};
2161 }
else if (lhs.is_vector() && rhs.is_vector()) {
2162 auto lhs_ =
static_cast<datum_impl::vector
>(lhs);
2163 ttlet &rhs_ = *(rhs.get_pointer<datum_impl::vector>());
2167 }
else if (lhs.is_map() && rhs.is_map()) {
2168 ttlet &lhs_ = *(lhs.get_pointer<datum_impl::map>());
2169 auto rhs_ =
static_cast<datum_impl::map
>(rhs);
2170 for (ttlet &item : lhs_) {
2171 rhs_.try_emplace(item.first, item.second);
2176 throw operation_error(
2177 "Can't add '+' value {} of type {} to value {} of type {}",
2185 friend datum_impl operator-(datum_impl
const &lhs, datum_impl
const &rhs)
2187 if (lhs.is_float() || rhs.is_float()) {
2188 ttlet lhs_ =
static_cast<double>(lhs);
2189 ttlet rhs_ =
static_cast<double>(rhs);
2190 return datum_impl{lhs_ - rhs_};
2192 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2193 ttlet lhs_ =
static_cast<decimal
>(lhs);
2194 ttlet rhs_ =
static_cast<decimal
>(rhs);
2195 return datum_impl{lhs_ - rhs_};
2197 }
else if (lhs.is_integer() || rhs.is_integer()) {
2198 ttlet lhs_ =
static_cast<long long int>(lhs);
2199 ttlet rhs_ =
static_cast<long long int>(rhs);
2200 return datum_impl{lhs_ - rhs_};
2203 throw operation_error(
2204 "Can't subtract '-' value {} of type {} from value {} of type {}",
2212 friend datum_impl operator*(datum_impl
const &lhs, datum_impl
const &rhs)
2214 if (lhs.is_float() || rhs.is_float()) {
2215 ttlet lhs_ =
static_cast<double>(lhs);
2216 ttlet rhs_ =
static_cast<double>(rhs);
2217 return datum_impl{lhs_ * rhs_};
2219 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2220 ttlet lhs_ =
static_cast<decimal
>(lhs);
2221 ttlet rhs_ =
static_cast<decimal
>(rhs);
2222 return datum_impl{lhs_ * rhs_};
2224 }
else if (lhs.is_integer() || rhs.is_integer()) {
2225 ttlet lhs_ =
static_cast<long long int>(lhs);
2226 ttlet rhs_ =
static_cast<long long int>(rhs);
2227 return datum_impl{lhs_ * rhs_};
2230 throw operation_error(
2231 "Can't multiply '*' value {} of type {} with value {} of type {}",
2239 friend datum_impl operator/(datum_impl
const &lhs, datum_impl
const &rhs)
2241 if (lhs.is_float() || rhs.is_float()) {
2242 ttlet lhs_ =
static_cast<double>(lhs);
2243 ttlet rhs_ =
static_cast<double>(rhs);
2244 return datum_impl{lhs_ / rhs_};
2246 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2247 ttlet lhs_ =
static_cast<decimal
>(lhs);
2248 ttlet rhs_ =
static_cast<decimal
>(rhs);
2249 return datum_impl{lhs_ / rhs_};
2251 }
else if (lhs.is_integer() || rhs.is_integer()) {
2252 ttlet lhs_ =
static_cast<long long int>(lhs);
2253 ttlet rhs_ =
static_cast<long long int>(rhs);
2254 return datum_impl{lhs_ / rhs_};
2256 }
else if (lhs.is_url() && (rhs.is_url() || rhs.is_string())) {
2257 ttlet lhs_ =
static_cast<URL
>(lhs);
2258 ttlet rhs_ =
static_cast<URL
>(rhs);
2259 return datum_impl{lhs_ / rhs_};
2262 throw operation_error(
2263 "Can't divide '/' value {} of type {} by value {} of type {}",
2271 friend datum_impl operator%(datum_impl
const &lhs, datum_impl
const &rhs)
2273 if (lhs.is_float() || rhs.is_float()) {
2274 ttlet lhs_ =
static_cast<double>(lhs);
2275 ttlet rhs_ =
static_cast<double>(rhs);
2276 return datum_impl{
fmod(lhs_, rhs_)};
2278 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2279 ttlet lhs_ =
static_cast<decimal
>(lhs);
2280 ttlet rhs_ =
static_cast<decimal
>(rhs);
2281 return datum_impl{lhs_ % rhs_};
2283 }
else if (lhs.is_integer() || rhs.is_integer()) {
2284 ttlet lhs_ =
static_cast<long long int>(lhs);
2285 ttlet rhs_ =
static_cast<long long int>(rhs);
2286 return datum_impl{lhs_ % rhs_};
2289 throw operation_error(
2290 "Can't take modulo '%' value {} of type {} by value {} of type {}",
2298 friend datum_impl operator<<(datum_impl
const &lhs, datum_impl
const &rhs)
2300 if (lhs.is_integer() && rhs.is_integer()) {
2301 ttlet lhs_ =
static_cast<long long>(lhs);
2302 ttlet rhs_ =
static_cast<long long>(rhs);
2309 throw operation_error(
"lhs value {} of left shift must not be negative", lhs);
2313 return datum_impl{0};
2315 return datum_impl{lhs_ << rhs_};
2319 throw operation_error(
2320 "Can't arithmetic shift-left '<<' value {} of type {} with value {} of type {}",
2328 friend datum_impl operator>>(datum_impl
const &lhs, datum_impl
const &rhs)
2330 if (lhs.is_integer() && rhs.is_integer()) {
2331 ttlet lhs_ =
static_cast<long long>(lhs);
2332 ttlet rhs_ =
static_cast<long long>(rhs);
2339 return lhs_ < 0 ? datum_impl{-1} : datum_impl{0};
2341 return datum_impl{lhs_ >> rhs_};
2345 throw operation_error(
2346 "Can't arithmetic shift-right '>>' value {} of type {} with value {} of type {}",
2354 friend datum_impl operator&(datum_impl
const &lhs, datum_impl
const &rhs)
2356 if (lhs.is_integer() && rhs.is_integer()) {
2357 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2358 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2359 return datum_impl{lhs_ & rhs_};
2362 throw operation_error(
2363 "Can't AND '&' value {} of type {} with value {} of type {}",
2371 friend datum_impl operator|(datum_impl
const &lhs, datum_impl
const &rhs)
2373 if (lhs.is_integer() && rhs.is_integer()) {
2374 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2375 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2376 return datum_impl{lhs_ | rhs_};
2379 throw operation_error(
2380 "Can't OR '|' value {} of type {} with value {} of type {}",
2388 friend datum_impl operator^(datum_impl
const &lhs, datum_impl
const &rhs)
2390 if (lhs.is_integer() && rhs.is_integer()) {
2391 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2392 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2393 return datum_impl{lhs_ ^ rhs_};
2396 throw operation_error(
2397 "Can't XOR '^' value {} of type {} with value {} of type {}",
2412 return os << static_cast<std::string>(d);
2415 friend void swap(datum_impl &lhs, datum_impl &rhs)
noexcept
2420 friend datum_impl pow(datum_impl
const &lhs, datum_impl
const &rhs)
2422 if (lhs.is_numeric() || rhs.is_numeric()) {
2423 ttlet lhs_ =
static_cast<double>(lhs);
2424 ttlet rhs_ =
static_cast<double>(rhs);
2425 return datum_impl{
std::pow(lhs_, rhs_)};
2428 throw operation_error(
2429 "Can't raise to a power '**' value {} of type {} with value {} of type {}",
2448 if (lhs.is_map() && rhs.is_map()) {
2452 for (
auto rhs_i = rhs.map_begin(); rhs_i != rhs.map_end(); rhs_i++) {
2453 auto result_i = result_map->
find(rhs_i->first);
2454 if (result_i == result_map->end()) {
2455 result_map->insert(*rhs_i);
2457 result_i->second =
deep_merge(result_i->second, rhs_i->second);
2461 }
else if (lhs.is_vector() && rhs.is_vector()) {
2465 for (
auto rhs_i = rhs.vector_begin(); rhs_i != rhs.vector_end(); rhs_i++) {
2476 template<
typename Alternative>
2477 friend bool holds_alternative(
datum_impl const &rhs)
noexcept
2479 if constexpr (std::is_same_v<Alternative, std::string>) {
2480 return rhs.is_string();