118 static constexpr uint64_t
make_string(std::string_view str)
120 ttlet len = str.size();
127 for (uint64_t i = 0; i < len; i++) {
131 return (string_mask + (len << 40)) | x;
140 static uint64_t make_pointer(uint64_t mask,
void *ptr)
142 return mask | (
reinterpret_cast<uint64_t
>(ptr) & pointer_mask);
150 static constexpr uint64_t id_to_mask(uint64_t
id)
163 static constexpr uint16_t make_id(uint16_t
id)
165 return ((
id & 0x10) << 11) | (
id & 0xf) | 0x7ff0;
169 static constexpr int64_t minimum_int = 0xffff'8000'0000'0000LL;
171 static constexpr int64_t maximum_int = 0x0000'7fff'ffff'ffffLL;
173 static constexpr int64_t minimum_mantissa = 0xffff'ff80'0000'0000LL;
174 static constexpr int64_t maximum_mantissa = 0x0000'007f'ffff'ffffLL;
176 static constexpr uint16_t exponent_mask = 0b0111'1111'1111'0000;
177 static constexpr uint64_t pointer_mask = 0x0000'ffff'ffff'ffff;
179 static constexpr uint64_t small_undefined = 0;
180 static constexpr uint64_t small_null = 1;
181 static constexpr uint64_t small_true = 2;
182 static constexpr uint64_t small_false = 3;
183 static constexpr uint64_t small_break = 4;
184 static constexpr uint64_t small_continue = 5;
186 static constexpr uint16_t phy_small_id = make_id(0b00001);
187 static constexpr uint16_t phy_decimal_id = make_id(0b00010);
188 static constexpr uint16_t phy_ymd_id = make_id(0b00011);
189 static constexpr uint16_t phy_integer_id = make_id(0b00100);
190 static constexpr uint16_t phy_string_id = make_id(0b00101);
191 static constexpr uint16_t phy_reserved_id0 = make_id(0b00110);
192 static constexpr uint16_t phy_reserved_id1 = make_id(0b00111);
193 static constexpr uint16_t phy_reserved_id2 = make_id(0b01000);
194 static constexpr uint16_t phy_reserved_id3 = make_id(0b01001);
195 static constexpr uint16_t phy_reserved_id4 = make_id(0b01010);
196 static constexpr uint16_t phy_reserved_id5 = make_id(0b01011);
197 static constexpr uint16_t phy_reserved_id6 = make_id(0b01100);
198 static constexpr uint16_t phy_reserved_id7 = make_id(0b01101);
199 static constexpr uint16_t phy_reserved_id8 = make_id(0b01110);
200 static constexpr uint16_t phy_reserved_id9 = make_id(0b01111);
202 static constexpr uint16_t phy_string_ptr_id = make_id(0b10001);
203 static constexpr uint16_t phy_url_ptr_id = make_id(0b10010);
204 static constexpr uint16_t phy_integer_ptr_id = make_id(0b10011);
205 static constexpr uint16_t phy_vector_ptr_id = make_id(0b10100);
206 static constexpr uint16_t phy_map_ptr_id = make_id(0b10101);
207 static constexpr uint16_t phy_decimal_ptr_id = make_id(0b10110);
208 static constexpr uint16_t phy_bytes_ptr_id = make_id(0b10111);
209 static constexpr uint16_t phy_reserved_ptr_id0 = make_id(0b11000);
210 static constexpr uint16_t phy_reserved_ptr_id1 = make_id(0b11001);
211 static constexpr uint16_t phy_reserved_ptr_id2 = make_id(0b11010);
212 static constexpr uint16_t phy_reserved_ptr_id3 = make_id(0b11011);
213 static constexpr uint16_t phy_reserved_ptr_id4 = make_id(0b11100);
214 static constexpr uint16_t phy_reserved_ptr_id5 = make_id(0b11101);
215 static constexpr uint16_t phy_reserved_ptr_id6 = make_id(0b11110);
216 static constexpr uint16_t phy_reserved_ptr_id7 = make_id(0b11111);
218 static constexpr uint64_t small_mask = id_to_mask(phy_small_id);
219 static constexpr uint64_t undefined_mask = small_mask | small_undefined;
220 static constexpr uint64_t null_mask = small_mask | small_null;
221 static constexpr uint64_t true_mask = small_mask | small_true;
222 static constexpr uint64_t false_mask = small_mask | small_false;
223 static constexpr uint64_t break_mask = small_mask | small_break;
224 static constexpr uint64_t continue_mask = small_mask | small_continue;
225 static constexpr uint64_t string_mask = id_to_mask(phy_string_id);
226 static constexpr uint64_t integer_mask = id_to_mask(phy_integer_id);
227 static constexpr uint64_t decimal_mask = id_to_mask(phy_decimal_id);
228 static constexpr uint64_t ymd_mask = id_to_mask(phy_ymd_id);
229 static constexpr uint64_t string_ptr_mask = id_to_mask(phy_string_ptr_id);
230 static constexpr uint64_t url_ptr_mask = id_to_mask(phy_url_ptr_id);
231 static constexpr uint64_t integer_ptr_mask = id_to_mask(phy_integer_ptr_id);
232 static constexpr uint64_t vector_ptr_mask = id_to_mask(phy_vector_ptr_id);
233 static constexpr uint64_t map_ptr_mask = id_to_mask(phy_map_ptr_id);
234 static constexpr uint64_t decimal_ptr_mask = id_to_mask(phy_decimal_ptr_id);
235 static constexpr uint64_t bytes_ptr_mask = id_to_mask(phy_bytes_ptr_id);
250 uint16_t type_id()
const noexcept
254 return static_cast<uint16_t
>(data >> 48);
257 bool is_phy_float()
const noexcept
259 ttlet
id = type_id();
260 return (
id & 0x7ff0) != 0x7ff0 || (
id & 0x000f) == 0;
263 bool is_phy_integer()
const noexcept
265 return type_id() == phy_integer_id;
268 bool is_phy_string()
const noexcept
270 return type_id() == phy_string_id;
273 bool is_phy_decimal()
const noexcept
275 return type_id() == phy_decimal_id;
278 bool is_phy_ymd()
const noexcept
280 return type_id() == phy_ymd_id;
283 bool is_phy_small()
const noexcept
285 return type_id() == phy_small_id;
288 bool is_phy_pointer()
const noexcept
290 return HasLargeObjects && (type_id() & 0xfff0) == 0xfff0;
293 bool is_phy_string_ptr()
const noexcept
295 return HasLargeObjects && type_id() == phy_string_ptr_id;
298 bool is_phy_url_ptr()
const noexcept
300 return HasLargeObjects && type_id() == phy_url_ptr_id;
303 bool is_phy_integer_ptr()
const noexcept
305 return HasLargeObjects && type_id() == phy_integer_ptr_id;
308 bool is_phy_vector_ptr()
const noexcept
310 return HasLargeObjects && type_id() == phy_vector_ptr_id;
313 bool is_phy_map_ptr()
const noexcept
315 return HasLargeObjects && type_id() == phy_map_ptr_id;
318 bool is_phy_decimal_ptr()
const noexcept
320 return HasLargeObjects && type_id() == phy_decimal_ptr_id;
323 bool is_phy_bytes_ptr()
const noexcept
325 return HasLargeObjects && type_id() == phy_bytes_ptr_id;
330 uint64_t get_unsigned_integer()
const noexcept
332 return (u64 << 16) >> 16;
337 int64_t get_signed_integer()
const noexcept
339 return static_cast<int64_t
>(u64 << 16) >> 16;
347 O *get_pointer()
const
349 return std::launder(
reinterpret_cast<O *
>(get_signed_integer()));
355 void delete_pointer()
noexcept
357 if constexpr (HasLargeObjects) {
359 case phy_integer_ptr_id:
delete get_pointer<int64_t>();
break;
360 case phy_string_ptr_id:
delete get_pointer<std::string>();
break;
361 case phy_url_ptr_id:
delete get_pointer<URL>();
break;
362 case phy_vector_ptr_id:
delete get_pointer<datum_impl::vector>();
break;
363 case phy_map_ptr_id:
delete get_pointer<datum_impl::map>();
break;
364 case phy_decimal_ptr_id:
delete get_pointer<decimal>();
break;
365 case phy_bytes_ptr_id:
delete get_pointer<bstring>();
break;
366 default: tt_no_default();
376 void copy_pointer(
datum_impl const &other)
noexcept
378 if constexpr (HasLargeObjects) {
379 switch (other.type_id()) {
380 case phy_integer_ptr_id: {
381 auto *
const p =
new int64_t(*other.get_pointer<int64_t>());
382 u64 = make_pointer(integer_ptr_mask, p);
385 case phy_string_ptr_id: {
387 u64 = make_pointer(string_ptr_mask, p);
390 case phy_url_ptr_id: {
391 auto *
const p =
new URL(*other.get_pointer<
URL>());
392 u64 = make_pointer(url_ptr_mask, p);
395 case phy_vector_ptr_id: {
397 u64 = make_pointer(vector_ptr_mask, p);
400 case phy_map_ptr_id: {
402 u64 = make_pointer(map_ptr_mask, p);
405 case phy_decimal_ptr_id: {
407 u64 = make_pointer(decimal_ptr_mask, p);
410 case phy_bytes_ptr_id: {
412 u64 = make_pointer(bytes_ptr_mask, p);
415 default: tt_no_default();
432 datum_impl() noexcept : u64(undefined_mask) {}
436 if (is_phy_pointer()) {
437 [[unlikely]] delete_pointer();
441 datum_impl(datum_impl
const &other)
noexcept
443 if (other.is_phy_pointer()) {
444 [[unlikely]] copy_pointer(other);
452 datum_impl &operator=(datum_impl
const &other)
noexcept
454 if (
this != &other) {
455 if (is_phy_pointer()) {
456 [[unlikely]] delete_pointer();
459 if (other.is_phy_pointer()) {
460 [[unlikely]] copy_pointer(other);
470 datum_impl(datum_impl &&other) noexcept : u64(undefined_mask)
474 other.u64 = undefined_mask;
477 datum_impl &operator=(datum_impl &&other)
noexcept
479 if (
this != &other) {
483 other.u64 = undefined_mask;
487 datum_impl(datum_impl::undefined) noexcept : u64(undefined_mask) {}
488 datum_impl(datum_impl::null) noexcept : u64(null_mask) {}
489 datum_impl(datum_impl::_break) noexcept : u64(break_mask) {}
490 datum_impl(datum_impl::_continue) noexcept : u64(continue_mask) {}
492 datum_impl(
double value) noexcept : f64(value)
494 if (value != value) {
495 u64 = undefined_mask;
498 datum_impl(
float value) noexcept : datum_impl(
static_cast<double>(value)) {}
500 datum_impl(decimal value)
noexcept
502 long long m = value.mantissa();
504 if (m < minimum_mantissa || m > maximum_mantissa) {
505 [[unlikely]]
if constexpr (HasLargeObjects)
507 auto *
const p =
new decimal(value);
508 u64 = make_pointer(decimal_ptr_mask, p);
515 int e = value.exponent();
517 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
521 datum_impl(date::year_month_day
const &ymd) noexcept :
523 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
524 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
525 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
526 0x0000ffff'ffffffff))
530 datum_impl(
unsigned long long value) noexcept : u64(integer_mask | value)
532 if (value > maximum_int) {
533 [[unlikely]]
if constexpr (HasLargeObjects)
535 auto *
const p =
new uint64_t(value);
536 u64 = make_pointer(integer_ptr_mask, p);
540 throw overflow_error(
"Constructing datum from integer {}, larger than {}", value, maximum_int);
544 datum_impl(
unsigned long value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
545 datum_impl(
unsigned int value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
546 datum_impl(
unsigned short value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
547 datum_impl(
unsigned char value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
549 datum_impl(
signed long long value) noexcept : u64(integer_mask | (
static_cast<uint64_t
>(value) & 0x0000ffff'ffffffff))
551 if (value < minimum_int || value > maximum_int)
554 if constexpr (HasLargeObjects) {
555 auto *
const p =
new int64_t(value);
556 u64 = make_pointer(integer_ptr_mask, p);
558 throw overflow_error(
559 "Constructing integer {} to datum, outside {} and {}", value, minimum_int, maximum_int);
563 datum_impl(
signed long value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
564 datum_impl(
signed int value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
565 datum_impl(
signed short value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
566 datum_impl(
signed char value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
568 datum_impl(
bool value) noexcept : u64(value ? true_mask : false_mask) {}
569 datum_impl(
char value) noexcept : u64(string_mask | (uint64_t{1} << 40) | value) {}
571 datum_impl(std::string_view value) noexcept : u64(make_string(value))
574 if constexpr (HasLargeObjects) {
576 u64 = make_pointer(string_ptr_mask, p);
578 throw std::overflow_error(fmt::format(
"Constructing string {} to datum, larger than 6 characters", value));
583 datum_impl(
std::string const &value) noexcept : datum_impl(std::string_view(value)) {}
584 datum_impl(
char const *value) noexcept : datum_impl(std::string_view(value)) {}
586 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
587 datum_impl(URL
const &value)
noexcept
589 auto *
const p =
new URL(value);
590 u64 = make_pointer(url_ptr_mask, p);
593 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
594 datum_impl(URL &&value)
noexcept
596 auto *
const p =
new URL(
std::move(value));
597 u64 = make_pointer(url_ptr_mask, p);
600 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
601 datum_impl(datum_impl::vector
const &value)
noexcept
603 auto *
const p =
new datum_impl::vector(value);
604 u64 = make_pointer(vector_ptr_mask, p);
607 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
608 datum_impl(datum_impl::vector &&value)
noexcept
610 auto *
const p =
new datum_impl::vector(
std::move(value));
611 u64 = make_pointer(vector_ptr_mask, p);
614 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
615 datum_impl(datum_impl::map
const &value)
noexcept
617 auto *
const p =
new datum_impl::map(value);
618 u64 = make_pointer(map_ptr_mask, p);
621 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
622 datum_impl(datum_impl::map &&value)
noexcept
624 auto *
const p =
new datum_impl::map(
std::move(value));
625 u64 = make_pointer(map_ptr_mask, p);
628 datum_impl &operator=(datum_impl::undefined rhs)
noexcept
630 if (is_phy_pointer()) {
631 [[unlikely]] delete_pointer();
633 u64 = undefined_mask;
637 datum_impl &operator=(datum_impl::null rhs)
noexcept
639 if (is_phy_pointer()) {
640 [[unlikely]] delete_pointer();
646 datum_impl &operator=(datum_impl::_break rhs)
noexcept
648 if (is_phy_pointer()) {
649 [[unlikely]] delete_pointer();
655 datum_impl &operator=(datum_impl::_continue rhs)
noexcept
657 if (is_phy_pointer()) {
658 [[unlikely]] delete_pointer();
664 datum_impl &operator=(
double rhs)
noexcept
666 if (is_phy_pointer()) {
667 [[unlikely]] delete_pointer();
673 u64 = undefined_mask;
677 datum_impl &operator=(
float rhs)
noexcept
679 return *
this =
static_cast<double>(rhs);
682 datum_impl &operator=(decimal rhs)
noexcept
684 if (is_phy_pointer()) {
685 [[unlikely]] delete_pointer();
688 long long m = rhs.mantissa();
689 if (m < minimum_mantissa || m > maximum_mantissa) {
690 [[unlikely]]
if constexpr (HasLargeObjects)
692 auto *
const p =
new decimal(rhs);
693 u64 = make_pointer(decimal_ptr_mask, p);
700 int e = rhs.exponent();
702 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
707 datum_impl &operator=(date::year_month_day
const &ymd)
noexcept
709 if (is_phy_pointer()) {
710 [[unlikely]] delete_pointer();
714 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
715 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
716 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
717 0x0000ffff'ffffffff);
721 datum_impl &operator=(
unsigned long long rhs)
723 if (is_phy_pointer()) {
724 [[unlikely]] delete_pointer();
727 u64 = integer_mask |
static_cast<uint64_t
>(rhs);
728 if (rhs > maximum_int) {
729 [[unlikely]]
if constexpr (HasLargeObjects)
731 auto *
const p =
new uint64_t(rhs);
732 u64 = make_pointer(integer_ptr_mask, p);
736 throw std::overflow_error(fmt::format(
"Assigning integer {} to datum, larger than {}", rhs, maximum_int));
741 datum_impl &operator=(
unsigned long rhs)
noexcept
743 return *
this =
static_cast<unsigned long long>(rhs);
745 datum_impl &operator=(
unsigned int rhs)
noexcept
747 return *
this =
static_cast<unsigned long long>(rhs);
749 datum_impl &operator=(
unsigned short rhs)
noexcept
751 return *
this =
static_cast<unsigned long long>(rhs);
753 datum_impl &operator=(
unsigned char rhs)
noexcept
755 return *
this =
static_cast<unsigned long long>(rhs);
758 datum_impl &operator=(
signed long long rhs)
noexcept
760 if (is_phy_pointer()) {
761 [[unlikely]] delete_pointer();
764 u64 = integer_mask | (
static_cast<uint64_t
>(rhs) & 0x0000ffff'ffffffff);
765 if (rhs < minimum_int || rhs > maximum_int) {
766 [[unlikely]]
if constexpr (HasLargeObjects)
768 auto *
const p =
new int64_t(rhs);
769 u64 = make_pointer(integer_ptr_mask, p);
773 throw overflow_error(
"Assigning integer {} to datum, outside {} and {}", rhs, minimum_int, maximum_int);
779 datum_impl &operator=(
signed long rhs)
noexcept
781 return *
this =
static_cast<signed long long>(rhs);
783 datum_impl &operator=(
signed int rhs)
noexcept
785 return *
this =
static_cast<signed long long>(rhs);
787 datum_impl &operator=(
signed short rhs)
noexcept
789 return *
this =
static_cast<signed long long>(rhs);
791 datum_impl &operator=(
signed char rhs)
noexcept
793 return *
this =
static_cast<signed long long>(rhs);
796 datum_impl &operator=(
bool rhs)
noexcept
798 if (is_phy_pointer()) {
799 [[unlikely]] delete_pointer();
801 u64 = rhs ? true_mask : false_mask;
805 datum_impl &operator=(
char rhs)
noexcept
807 if (is_phy_pointer()) {
808 [[unlikely]] delete_pointer();
810 u64 = string_mask | (uint64_t{1} << 40) |
static_cast<uint64_t
>(rhs);
814 datum_impl &operator=(std::string_view rhs)
816 if (is_phy_pointer()) {
817 [[unlikely]] delete_pointer();
820 u64 = make_string(rhs);
822 if constexpr (HasLargeObjects) {
824 u64 = make_pointer(string_ptr_mask, p);
826 throw std::overflow_error(fmt::format(
"Assigning string {} to datum, larger than 6 characters", rhs));
834 *
this = std::string_view{rhs};
838 datum_impl &operator=(
char const *rhs)
840 *
this = std::string_view{rhs};
844 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
845 datum_impl &operator=(URL
const &rhs)
noexcept
847 if (is_phy_pointer()) {
848 [[unlikely]] delete_pointer();
851 auto *
const p =
new URL(rhs);
852 u64 = make_pointer(url_ptr_mask, p);
856 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
857 datum_impl &operator=(URL &&rhs)
noexcept
859 if (is_phy_pointer()) {
860 [[unlikely]] delete_pointer();
864 u64 = make_pointer(url_ptr_mask, p);
868 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
869 datum_impl &operator=(datum_impl::vector
const &rhs)
871 if (is_phy_pointer()) {
872 [[unlikely]] delete_pointer();
875 auto *
const p =
new datum_impl::vector(rhs);
876 u64 = make_pointer(vector_ptr_mask, p);
881 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
882 datum_impl &operator=(datum_impl::vector &&rhs)
884 if (is_phy_pointer()) {
885 [[unlikely]] delete_pointer();
888 auto *
const p =
new datum_impl::vector(
std::move(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::map
const &rhs)
897 if (is_phy_pointer()) {
898 [[unlikely]] delete_pointer();
901 auto *
const p =
new datum_impl::map(rhs);
902 u64 = make_pointer(map_ptr_mask, p);
907 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
908 datum_impl &operator=(datum_impl::map &&rhs)
910 if (is_phy_pointer()) {
911 [[unlikely]] delete_pointer();
914 auto *
const p =
new datum_impl::map(
std::move(rhs));
915 u64 = make_pointer(map_ptr_mask, p);
920 explicit operator double()
const
922 if (is_phy_float()) {
924 }
else if (is_decimal()) {
925 return static_cast<double>(
static_cast<decimal
>(*this));
926 }
else if (is_phy_integer()) {
927 return static_cast<double>(get_signed_integer());
928 }
else if (is_phy_integer_ptr()) {
929 return static_cast<double>(*get_pointer<int64_t>());
931 throw operation_error(
932 "Value {} of type {} can not be converted to a double", this->repr(), this->type_name());
936 explicit operator float()
const
938 return static_cast<float>(
static_cast<double>(*this));
941 explicit operator decimal()
const
943 if (is_phy_decimal()) {
944 uint64_t v = get_unsigned_integer();
945 int e =
static_cast<int8_t
>(v);
946 long long m =
static_cast<int64_t
>(v << 16) >> 24;
947 return decimal{e, m};
948 }
else if (is_phy_decimal_ptr()) {
949 return *get_pointer<decimal>();
950 }
else if (is_phy_integer() || is_phy_integer_ptr()) {
951 return decimal{
static_cast<signed long long>(*this)};
952 }
else if (is_phy_float()) {
953 return decimal{
static_cast<double>(*this)};
955 throw operation_error(
956 "Value {} of type {} can not be converted to a decimal", this->repr(), this->type_name());
960 explicit operator date::year_month_day()
const
963 ttlet u = get_unsigned_integer();
964 ttlet i = get_signed_integer();
965 ttlet day =
static_cast<unsigned>(u & 0x1f);
966 ttlet month =
static_cast<unsigned>((u >> 5) & 0xf);
967 ttlet year =
static_cast<signed>(i >> 9);
970 throw operation_error(
971 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
974 throw operation_error(
975 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
977 return date::year_month_day{date::year{year}, date::month{month}, date::day{day}};
979 throw operation_error(
980 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
984 explicit operator signed long long()
const
986 if (is_phy_integer()) {
987 return get_signed_integer();
988 }
else if (is_phy_integer_ptr()) {
989 return *get_pointer<signed long long>();
990 }
else if (is_phy_float()) {
991 return static_cast<signed long long>(f64);
992 }
else if (is_phy_small()) {
993 switch (get_unsigned_integer()) {
994 case small_true:
return 1;
995 case small_false:
return 0;
998 throw operation_error(
999 "Value {} of type {} can not be converted to a signed long long", this->repr(), this->type_name());
1002 explicit operator signed long()
const
1004 ttlet v =
static_cast<signed long long>(*this);
1006 throw operation_error(
1007 "Value {} of type {} can not be converted to a signed long", this->repr(), this->type_name());
1009 return static_cast<signed long>(v);
1012 explicit operator signed int()
const
1014 ttlet v =
static_cast<signed long long>(*this);
1016 throw operation_error(
1017 "Value {} of type {} can not be converted to a signed int", this->repr(), this->type_name());
1019 return static_cast<signed int>(v);
1022 explicit operator signed short()
const
1024 ttlet v =
static_cast<signed long long>(*this);
1026 throw operation_error(
1027 "Value {} of type {} can not be converted to a signed short", this->repr(), this->type_name());
1029 return static_cast<signed short>(v);
1032 explicit operator signed char()
const
1034 ttlet v =
static_cast<int64_t
>(*this);
1036 throw operation_error(
1037 "Value {} of type {} can not be converted to a signed char", this->repr(), this->type_name());
1039 return static_cast<signed char>(v);
1042 explicit operator unsigned long long()
const
1044 ttlet v =
static_cast<signed long long>(*this);
1046 throw operation_error(
1047 "Value {} of type {} can not be converted to a unsigned long long", this->repr(), this->type_name());
1049 return static_cast<unsigned long long>(v);
1052 explicit operator unsigned long()
const
1054 ttlet v =
static_cast<unsigned long long>(*this);
1056 throw operation_error(
1057 "Value {} of type {} can not be converted to a unsigned long", this->repr(), this->type_name());
1059 return static_cast<unsigned long>(v);
1062 explicit operator unsigned int()
const
1064 ttlet v =
static_cast<unsigned long long>(*this);
1066 throw operation_error(
1067 "Value {} of type {} can not be converted to a unsigned int", this->repr(), this->type_name());
1069 return static_cast<unsigned int>(v);
1072 explicit operator unsigned short()
const
1074 ttlet v =
static_cast<unsigned long long>(*this);
1076 throw operation_error(
1077 "Value {} of type {} can not be converted to a unsigned short", this->repr(), this->type_name());
1079 return static_cast<unsigned short>(v);
1082 explicit operator unsigned char()
const
1084 ttlet v =
static_cast<unsigned long long>(*this);
1086 throw operation_error(
1087 "Value {} of type {} can not be converted to a unsigned char", this->repr(), this->type_name());
1089 return static_cast<unsigned char>(v);
1092 explicit operator bool() const noexcept
1094 switch (type_id()) {
1095 case phy_small_id:
return get_unsigned_integer() == small_true;
1096 case phy_integer_id:
return static_cast<int64_t
>(*this) != 0;
1097 case phy_decimal_id:
return static_cast<decimal
>(*this) != 0;
1098 case phy_ymd_id:
return true;
1099 case phy_integer_ptr_id:
return *get_pointer<int64_t>() != 0;
1101 case phy_string_ptr_id:
return this->size() > 0;
1102 case phy_url_ptr_id:
return true;
1103 case phy_vector_ptr_id:
return this->size() > 0;
1104 case phy_map_ptr_id:
return this->size() > 0;
1105 case phy_decimal_ptr_id:
return static_cast<decimal
>(*this) != 0;
1106 case phy_bytes_ptr_id:
return this->size() > 0;
1108 if (is_phy_float()) {
1109 return static_cast<double>(*this) != 0.0;
1116 explicit operator char()
const
1118 if (is_phy_string() && size() == 1) {
1120 }
else if (is_phy_string_ptr() && size() == 1) {
1121 return get_pointer<std::string>()->at(0);
1123 throw operation_error(
1124 "Value {} of type {} can not be converted to a char", this->repr(), this->type_name());
1128 explicit operator bstring()
const
1131 if constexpr (HasLargeObjects) {
1132 return *get_pointer<bstring>();
1137 throw operation_error(
1138 "Value {} of type {} can not be converted to bytes", this->repr(), this->type_name());
1144 switch (type_id()) {
1146 switch (get_unsigned_integer()) {
1147 case small_undefined:
return "undefined";
1148 case small_null:
return "null";
1149 case small_true:
return "true";
1150 case small_false:
return "false";
1151 case small_break:
return "break";
1152 case small_continue:
return "continue";
1153 default: tt_no_default();
1156 case phy_integer_id:
return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1157 case phy_decimal_id:
return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1158 case phy_ymd_id:
return fmt::format(
"{}",
static_cast<date::year_month_day
>(*
this));
1159 case phy_integer_ptr_id:
1160 if constexpr (HasLargeObjects) {
1161 return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1166 case phy_string_id: {
1167 ttlet length = size();
1169 for (
int i = 0; i < length; i++) {
1170 buffer[i] = (u64 >> ((length - i - 1) * 8)) & 0xff;
1175 case phy_string_ptr_id:
1176 if constexpr (HasLargeObjects) {
1177 return *get_pointer<std::string>();
1182 case phy_url_ptr_id:
1183 if constexpr (HasLargeObjects) {
1184 return to_string(*get_pointer<URL>());
1189 case phy_decimal_ptr_id:
1190 if constexpr (HasLargeObjects) {
1191 return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1196 case phy_vector_ptr_id:
1197 if constexpr (HasLargeObjects) {
1200 for (
auto i = vector_begin(); i != vector_end(); i++) {
1212 case phy_map_ptr_id:
1213 if constexpr (HasLargeObjects) {
1218 return a.first < b.first;
1223 for (
auto &item : items) {
1227 r += item.first.repr();
1229 r += item.second.repr();
1237 case phy_bytes_ptr_id:
1238 if constexpr (HasLargeObjects) {
1245 if (is_phy_float()) {
1246 auto str = fmt::format(
"{:g}",
static_cast<double>(*
this));
1247 if (str.find(
'.') == str.npos) {
1257 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1258 explicit operator URL()
const
1262 }
else if (is_url()) {
1263 return *get_pointer<URL>();
1265 throw operation_error(
1266 "Value {} of type {} can not be converted to a URL", this->repr(), this->type_name());
1270 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1271 explicit operator datum_impl::vector()
const
1274 return *get_pointer<datum_impl::vector>();
1276 throw operation_error(
1277 "Value {} of type {} can not be converted to a Vector", this->repr(), this->type_name());
1281 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1282 explicit operator datum_impl::map()
const
1285 return *get_pointer<datum_impl::map>();
1287 throw operation_error(
1288 "Value {} of type {} can not be converted to a Map", this->repr(), this->type_name());
1299 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1302 if (is_undefined()) {
1305 u64 = map_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1309 auto &m = *get_pointer<datum_impl::map>();
1310 auto [i, did_insert] = m.try_emplace(rhs);
1313 }
else if (is_vector() && rhs.is_integer()) {
1314 auto index =
static_cast<int64_t
>(rhs);
1315 auto &v = *get_pointer<datum_impl::vector>();
1318 index = std::ssize(v) + index;
1321 if (index < 0 || index >= std::ssize(v)) {
1323 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1329 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1340 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1344 ttlet &m = *get_pointer<datum_impl::map>();
1345 ttlet i = m.find(rhs);
1346 if (i == m.cend()) {
1347 throw operation_error(
"Could not find key {} in map of size {}", rhs.repr(), std::ssize(m));
1351 }
else if (is_vector() && rhs.is_integer()) {
1352 auto index =
static_cast<int64_t
>(rhs);
1353 ttlet &v = *get_pointer<datum_impl::vector>();
1356 index = std::ssize(v) + index;
1359 if (index < 0 || index >= std::ssize(v)) {
1361 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1367 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1379 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1383 ttlet &m = *get_pointer<datum_impl::map>();
1384 ttlet i = m.find(rhs);
1385 return i != m.cend();
1387 }
else if (is_vector() && rhs.is_integer()) {
1388 auto index =
static_cast<int64_t
>(rhs);
1389 ttlet &v = *get_pointer<datum_impl::vector>();
1392 index = std::ssize(v) + index;
1395 return index >= 0 && index < std::ssize(v);
1407 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1410 if (is_undefined()) {
1413 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1417 auto *v = get_pointer<datum_impl::vector>();
1422 throw operation_error(
"Cannot append new item onto type {}", type_name());
1426 template<
typename... Args>
1427 void emplace_back(Args &&... args)
1429 if (is_undefined()) {
1432 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1436 auto *v = get_pointer<datum_impl::vector>();
1437 v->emplace_back(std::forward<Args>(args)...);
1440 throw operation_error(
"Cannot append new item onto type {}", type_name());
1444 template<
typename Arg>
1445 void push_back(Arg &&arg)
1447 if (is_undefined()) {
1449 auto *p =
new datum_impl::vector();
1450 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1454 auto *v = get_pointer<datum_impl::vector>();
1455 v->push_back(std::forward<Arg>(arg));
1458 throw operation_error(
"Cannot append new item onto type {}", type_name());
1465 auto *v = get_pointer<datum_impl::vector>();
1469 throw operation_error(
"Cannot pop_back() onto type {}", type_name());
1473 datum_impl year()
const
1476 return {
static_cast<signed>(
static_cast<date::year_month_day
>(*this).year())};
1478 throw operation_error(
"Cannot get year() from type {}", type_name());
1482 datum_impl quarter()
const
1485 auto month =
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month());
1486 return {((month - 1) / 3) + 1};
1488 throw operation_error(
"Cannot get month() from type {}", type_name());
1492 datum_impl month()
const
1495 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month())};
1497 throw operation_error(
"Cannot get month() from type {}", type_name());
1501 datum_impl day()
const
1504 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).day())};
1506 throw operation_error(
"Cannot get day() from type {}", type_name());
1510 datum_impl
const &front()
const
1513 ttlet *v = get_pointer<datum_impl::vector>();
1517 throw operation_error(
"Cannot front() onto type {}", type_name());
1524 auto *v = get_pointer<datum_impl::vector>();
1528 throw operation_error(
"Cannot front() onto type {}", type_name());
1532 datum_impl
const &back()
const
1535 ttlet *v = get_pointer<datum_impl::vector>();
1539 throw operation_error(
"Cannot back() onto type {}", type_name());
1546 auto *v = get_pointer<datum_impl::vector>();
1550 throw operation_error(
"Cannot back() onto type {}", type_name());
1556 switch (type_id()) {
1558 switch (get_unsigned_integer()) {
1559 case small_undefined:
return "undefined";
1560 case small_null:
return "null";
1561 case small_true:
return "true";
1562 case small_false:
return "false";
1563 case small_break:
return "break";
1564 case small_continue:
return "continue";
1565 default: tt_no_default();
1567 case phy_integer_id:
1568 case phy_integer_ptr_id:
return static_cast<std::string>(*this);
1569 case phy_decimal_id:
1570 case phy_decimal_ptr_id:
return static_cast<std::string>(*this);
1571 case phy_ymd_id:
return static_cast<std::string>(*this);
1573 case phy_string_ptr_id:
return fmt::format(
"\"{}\"",
static_cast<std::string>(*
this));
1574 case phy_url_ptr_id:
return fmt::format(
"<URL {}>",
static_cast<std::string>(*
this));
1575 case phy_vector_ptr_id:
return static_cast<std::string>(*this);
1576 case phy_map_ptr_id:
return static_cast<std::string>(*this);
1577 case phy_bytes_ptr_id:
return static_cast<std::string>(*this);
1579 if (is_phy_float()) {
1594 return phy_integer_id;
1602 if (key.
size() > 0 && is_map()) {
1603 ttlet index = key.
at(0);
1604 auto &next = (*this)[index];
1606 return next.get_by_path(next_key);
1608 }
else if (key.
size() > 0 && is_vector()) {
1610 auto &
next = (*this)[index];
1612 return next.get_by_path(next_key);
1614 }
else if (key.
size() > 0) {
1615 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1623 if (key.
size() > 0 && is_map()) {
1624 ttlet index = key.
at(0);
1625 ttlet
next = (*this)[index];
1628 }
else if (key.
size() > 0 && is_vector()) {
1630 ttlet
next = (*this)[index];
1633 }
else if (key.
size() > 0) {
1634 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1640 bool is_integer() const noexcept
1642 return is_phy_integer() || is_phy_integer_ptr();
1644 bool is_decimal() const noexcept
1646 return is_phy_decimal() || is_phy_decimal_ptr();
1648 bool is_ymd() const noexcept
1650 return is_phy_ymd();
1652 bool is_float() const noexcept
1654 return is_phy_float();
1656 bool is_string() const noexcept
1658 return is_phy_string() || is_phy_string_ptr();
1660 bool is_bytes() const noexcept
1662 return is_phy_bytes_ptr();
1665 bool is_bool() const noexcept
1667 if (is_phy_small()) {
1668 ttlet tmp = get_unsigned_integer();
1669 return tmp == small_true || tmp == small_false;
1675 bool is_null() const noexcept
1677 return is_phy_small() && get_unsigned_integer() == small_null;
1680 bool is_undefined() const noexcept
1682 return is_phy_small() && get_unsigned_integer() == small_undefined;
1685 bool is_break() const noexcept
1687 return is_phy_small() && get_unsigned_integer() == small_break;
1690 bool is_continue() const noexcept
1692 return is_phy_small() && get_unsigned_integer() == small_continue;
1694 bool is_url() const noexcept
1696 return is_phy_url_ptr();
1699 bool is_vector() const noexcept
1701 return is_phy_vector_ptr();
1703 bool is_map() const noexcept
1705 return is_phy_map_ptr();
1707 bool is_numeric() const noexcept
1709 return is_integer() || is_decimal() || is_float();
1712 datum_type_t type() const noexcept
1714 switch (type_id()) {
1716 switch (get_unsigned_integer()) {
1717 case small_undefined:
return datum_type_t::Undefined;
1718 case small_null:
return datum_type_t::Null;
1719 case small_false:
return datum_type_t::Boolean;
1720 case small_true:
return datum_type_t::Boolean;
1721 case small_break:
return datum_type_t::Break;
1722 case small_continue:
return datum_type_t::Continue;
1723 default: tt_no_default();
1726 case phy_integer_id:
1727 case phy_integer_ptr_id:
return datum_type_t::Integer;
1728 case phy_decimal_id:
1729 case phy_decimal_ptr_id:
return datum_type_t::Decimal;
1730 case phy_ymd_id:
return datum_type_t::YearMonthDay;
1732 case phy_string_ptr_id:
return datum_type_t::String;
1733 case phy_url_ptr_id:
return datum_type_t::URL;
1734 case phy_vector_ptr_id:
return datum_type_t::Vector;
1735 case phy_map_ptr_id:
return datum_type_t::Map;
1736 case phy_bytes_ptr_id:
return datum_type_t::Bytes;
1738 if (is_phy_float()) {
1739 return datum_type_t::Float;
1746 char const *type_name() const noexcept
1748 switch (type_id()) {
1750 switch (get_unsigned_integer()) {
1751 case small_undefined:
return "Undefined";
1752 case small_null:
return "Null";
1753 case small_false:
return "Boolean";
1754 case small_true:
return "Boolean";
1755 case small_break:
return "Break";
1756 case small_continue:
return "Continue";
1757 default: tt_no_default();
1760 case phy_integer_id:
1761 case phy_integer_ptr_id:
return "Integer";
1762 case phy_decimal_id:
1763 case phy_decimal_ptr_id:
return "Decimal";
1764 case phy_ymd_id:
return "YearMonthDay";
1766 case phy_string_ptr_id:
return "String";
1767 case phy_url_ptr_id:
return "URL";
1768 case phy_vector_ptr_id:
return "Vector";
1769 case phy_map_ptr_id:
return "Map";
1770 case phy_bytes_ptr_id:
return "Bytes";
1772 if (is_phy_float()) {
1782 switch (type_id()) {
1783 case phy_string_id:
return (u64 >> 40) & 0xff;
1784 case phy_string_ptr_id:
return get_pointer<std::string>()->size();
1785 case phy_vector_ptr_id:
return get_pointer<datum_impl::vector>()->size();
1786 case phy_map_ptr_id:
return get_pointer<datum_impl::map>()->size();
1787 case phy_bytes_ptr_id:
return get_pointer<bstring>()->size();
1788 default:
throw operation_error(
"Can't get size of value {} of type {}.", this->repr(), this->type_name());
1792 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1793 typename map::const_iterator map_begin()
const
1795 if (is_phy_map_ptr()) {
1796 return get_pointer<datum_impl::map>()->begin();
1798 throw operation_error(
"map_begin() expect datum to be a map, but it is a {}.", this->type_name());
1802 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1803 typename map::const_iterator map_end()
const
1805 if (is_phy_map_ptr()) {
1806 return get_pointer<datum_impl::map>()->end();
1808 throw operation_error(
"map_end() expect datum to be a map, but it is a {}.", this->type_name());
1812 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1813 typename vector::const_iterator vector_begin()
const
1815 if (is_phy_vector_ptr()) {
1816 return get_pointer<datum_impl::vector>()->begin();
1818 throw operation_error(
1819 "vector_begin() expect datum to be a vector, but it is a {}.", this->type_name());
1823 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1824 typename vector::const_iterator vector_end()
const
1826 if (is_phy_vector_ptr()) {
1827 return get_pointer<datum_impl::vector>()->end();
1829 throw operation_error(
"vector_end() expect datum to be a vector, but it is a {}.", this->type_name());
1833 size_t hash() const noexcept
1835 if (is_phy_float()) {
1837 }
else if (is_phy_pointer()) {
1838 [[unlikely]]
switch (type_id())
1841 case phy_url_ptr_id:
return std::hash<URL>{}(*get_pointer<URL>());
1842 case phy_vector_ptr_id:
1843 return std::accumulate(vector_begin(), vector_end(),
size_t{0}, [](
size_t a,
auto x) {
1844 return a ^ x.hash();
1846 case phy_map_ptr_id:
1847 return std::accumulate(map_begin(), map_end(),
size_t{0}, [](
size_t a,
auto x) {
1848 return a ^ (x.first.hash() ^ x.second.hash());
1852 default: tt_no_default();
1859 datum_impl &operator++()
1861 if (!this->is_numeric()) {
1862 throw operation_error(
"Can't increment '++' value {} of type {}", this->repr(), this->type_name());
1868 datum_impl &operator--()
1870 if (!this->is_numeric()) {
1871 throw operation_error(
"Can't increment '--' value {} of type {}", this->repr(), this->type_name());
1877 datum_impl operator++(
int)
1884 datum_impl operator--(
int)
1891 datum_impl &operator+=(datum_impl
const &rhs)
1893 if (this->is_vector()) {
1894 this->push_back(rhs);
1896 *
this = *
this + rhs;
1901 datum_impl &operator-=(datum_impl
const &rhs)
1903 return *
this = *
this - rhs;
1906 datum_impl &operator*=(datum_impl
const &rhs)
1908 return *
this = *
this * rhs;
1911 datum_impl &operator/=(datum_impl
const &rhs)
1913 return *
this = *
this / rhs;
1916 datum_impl &operator%=(datum_impl
const &rhs)
1918 return *
this = *
this % rhs;
1921 datum_impl &operator<<=(datum_impl
const &rhs)
1923 return *
this = *
this << rhs;
1926 datum_impl &operator>>=(datum_impl
const &rhs)
1928 return *
this = *
this >> rhs;
1931 datum_impl &operator&=(datum_impl
const &rhs)
1933 return *
this = *
this & rhs;
1936 datum_impl &operator|=(datum_impl
const &rhs)
1938 return *
this = *
this | rhs;
1941 datum_impl &operator^=(datum_impl
const &rhs)
1943 return *
this = *
this ^ rhs;
1946 friend datum_impl operator~(datum_impl
const &rhs)
1948 if (rhs.is_integer()) {
1949 return datum_impl{~static_cast<int64_t>(rhs)};
1951 throw operation_error(
"Can't bit-wise negate '~' value {} of type {}", rhs.repr(), rhs.type_name());
1955 friend datum_impl operator-(datum_impl
const &rhs)
1957 if (rhs.is_integer()) {
1958 return datum_impl{-
static_cast<int64_t
>(rhs)};
1959 }
else if (rhs.is_decimal()) {
1960 return datum_impl{-
static_cast<decimal
>(rhs)};
1961 }
else if (rhs.is_float()) {
1962 return datum_impl{-
static_cast<double>(rhs)};
1964 throw operation_error(
"Can't arithmetic negate '-' value {} of type {}", rhs.repr(), rhs.type_name());
1968 friend datum_impl operator+(datum_impl
const &rhs)
1970 if (rhs.is_numeric()) {
1973 throw operation_error(
"Can't arithmetic posgate '+' value {} of type {}", rhs.repr(), rhs.type_name());
1977 friend bool operator==(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
1979 switch (lhs.type_id()) {
1980 case datum_impl::phy_small_id:
return rhs.is_phy_small() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1981 case datum_impl::phy_integer_id:
1982 case datum_impl::phy_integer_ptr_id:
1984 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1985 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1986 (rhs.is_integer() &&
static_cast<int64_t
>(lhs) ==
static_cast<int64_t
>(rhs)));
1987 case datum_impl::phy_decimal_id:
1988 case datum_impl::phy_decimal_ptr_id:
1990 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1991 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1992 (rhs.is_integer() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)));
1993 case datum_impl::phy_ymd_id:
return rhs.is_ymd() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1994 case datum_impl::phy_string_id:
1995 case datum_impl::phy_string_ptr_id:
1998 (rhs.is_url() &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs)));
1999 case datum_impl::phy_url_ptr_id:
2000 return (rhs.is_url() || rhs.is_string()) &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs);
2001 case datum_impl::phy_vector_ptr_id:
2002 return rhs.is_vector() && *lhs.get_pointer<datum_impl::vector>() == *rhs.get_pointer<datum_impl::vector>();
2003 case datum_impl::phy_map_ptr_id:
2004 return rhs.is_map() && *lhs.get_pointer<datum_impl::map>() == *rhs.get_pointer<datum_impl::map>();
2005 case datum_impl::phy_bytes_ptr_id:
return (rhs.is_bytes() &&
static_cast<bstring
>(lhs) ==
static_cast<bstring
>(rhs));
2007 if (lhs.is_phy_float()) {
2008 return rhs.is_numeric() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs);
2015 friend bool operator<(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2017 switch (lhs.type_id()) {
2018 case datum_impl::phy_small_id:
2019 if (lhs.is_bool() && rhs.is_bool()) {
2020 return static_cast<bool>(lhs) <
static_cast<bool>(rhs);
2022 return lhs.get_unsigned_integer() < rhs.get_unsigned_integer();
2024 case datum_impl::phy_integer_id:
2025 case datum_impl::phy_integer_ptr_id:
2026 if (rhs.is_float()) {
2027 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2028 }
else if (rhs.is_decimal()) {
2029 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2030 }
else if (rhs.is_integer()) {
2031 return static_cast<int64_t
>(lhs) <
static_cast<int64_t
>(rhs);
2033 return lhs.type_order() < rhs.type_order();
2035 case datum_impl::phy_decimal_id:
2036 case datum_impl::phy_decimal_ptr_id:
2037 if (rhs.is_float()) {
2038 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2039 }
else if (rhs.is_decimal()) {
2040 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2041 }
else if (rhs.is_integer()) {
2042 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2044 return lhs.type_order() < rhs.type_order();
2046 case datum_impl::phy_ymd_id:
2048 return static_cast<date::year_month_day
>(lhs) <
static_cast<date::year_month_day
>(rhs);
2050 return lhs.type_order() < rhs.type_order();
2052 case datum_impl::phy_string_id:
2053 case datum_impl::phy_string_ptr_id:
2054 if (rhs.is_string()) {
2056 }
else if (rhs.is_url()) {
2057 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2059 return lhs.type_order() < rhs.type_order();
2061 case datum_impl::phy_url_ptr_id:
2062 if (rhs.is_url() || rhs.is_string()) {
2063 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2065 return lhs.type_order() < rhs.type_order();
2067 case datum_impl::phy_vector_ptr_id:
2068 if (rhs.is_vector()) {
2069 return *lhs.get_pointer<datum_impl::vector>() < *rhs.get_pointer<datum_impl::vector>();
2071 return lhs.type_order() < rhs.type_order();
2073 case datum_impl::phy_map_ptr_id:
2075 return *lhs.get_pointer<datum_impl::map>() < *rhs.get_pointer<datum_impl::map>();
2077 return lhs.type_order() < rhs.type_order();
2079 case datum_impl::phy_bytes_ptr_id:
2080 if (rhs.is_bytes()) {
2081 return static_cast<bstring
>(lhs) <
static_cast<bstring
>(rhs);
2083 return lhs.type_order() < rhs.type_order();
2086 if (lhs.is_phy_float()) {
2087 if (rhs.is_numeric()) {
2088 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2090 return lhs.type_order() < rhs.type_order();
2098 friend bool operator!=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2100 return !(lhs == rhs);
2103 friend bool operator>(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2108 friend bool operator<=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2110 return !(rhs < lhs);
2113 friend bool operator>=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2115 return !(lhs < rhs);
2118 friend datum_impl operator+(datum_impl
const &lhs, datum_impl
const &rhs)
2120 if (lhs.is_float() || rhs.is_float()) {
2121 ttlet lhs_ =
static_cast<double>(lhs);
2122 ttlet rhs_ =
static_cast<double>(rhs);
2123 return datum_impl{lhs_ + rhs_};
2125 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2126 ttlet lhs_ =
static_cast<decimal
>(lhs);
2127 ttlet rhs_ =
static_cast<decimal
>(rhs);
2128 return datum_impl{lhs_ + rhs_};
2130 }
else if (lhs.is_integer() || rhs.is_integer()) {
2131 ttlet lhs_ =
static_cast<long long int>(lhs);
2132 ttlet rhs_ =
static_cast<long long int>(rhs);
2133 return datum_impl{lhs_ + rhs_};
2135 }
else if (lhs.is_string() && rhs.is_string()) {
2138 return datum_impl{
std::move(lhs_ + rhs_)};
2140 }
else if (lhs.is_vector() && rhs.is_vector()) {
2141 auto lhs_ =
static_cast<datum_impl::vector
>(lhs);
2142 ttlet &rhs_ = *(rhs.get_pointer<datum_impl::vector>());
2146 }
else if (lhs.is_map() && rhs.is_map()) {
2147 ttlet &lhs_ = *(lhs.get_pointer<datum_impl::map>());
2148 auto rhs_ =
static_cast<datum_impl::map
>(rhs);
2149 for (ttlet &item : lhs_) {
2150 rhs_.try_emplace(item.first, item.second);
2155 throw operation_error(
2156 "Can't add '+' value {} of type {} to value {} of type {}",
2164 friend datum_impl operator-(datum_impl
const &lhs, datum_impl
const &rhs)
2166 if (lhs.is_float() || rhs.is_float()) {
2167 ttlet lhs_ =
static_cast<double>(lhs);
2168 ttlet rhs_ =
static_cast<double>(rhs);
2169 return datum_impl{lhs_ - rhs_};
2171 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2172 ttlet lhs_ =
static_cast<decimal
>(lhs);
2173 ttlet rhs_ =
static_cast<decimal
>(rhs);
2174 return datum_impl{lhs_ - rhs_};
2176 }
else if (lhs.is_integer() || rhs.is_integer()) {
2177 ttlet lhs_ =
static_cast<long long int>(lhs);
2178 ttlet rhs_ =
static_cast<long long int>(rhs);
2179 return datum_impl{lhs_ - rhs_};
2182 throw operation_error(
2183 "Can't subtract '-' value {} of type {} from value {} of type {}",
2191 friend datum_impl operator*(datum_impl
const &lhs, datum_impl
const &rhs)
2193 if (lhs.is_float() || rhs.is_float()) {
2194 ttlet lhs_ =
static_cast<double>(lhs);
2195 ttlet rhs_ =
static_cast<double>(rhs);
2196 return datum_impl{lhs_ * rhs_};
2198 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2199 ttlet lhs_ =
static_cast<decimal
>(lhs);
2200 ttlet rhs_ =
static_cast<decimal
>(rhs);
2201 return datum_impl{lhs_ * rhs_};
2203 }
else if (lhs.is_integer() || rhs.is_integer()) {
2204 ttlet lhs_ =
static_cast<long long int>(lhs);
2205 ttlet rhs_ =
static_cast<long long int>(rhs);
2206 return datum_impl{lhs_ * rhs_};
2209 throw operation_error(
2210 "Can't multiply '*' value {} of type {} with value {} of type {}",
2218 friend datum_impl operator/(datum_impl
const &lhs, datum_impl
const &rhs)
2220 if (lhs.is_float() || rhs.is_float()) {
2221 ttlet lhs_ =
static_cast<double>(lhs);
2222 ttlet rhs_ =
static_cast<double>(rhs);
2223 return datum_impl{lhs_ / rhs_};
2225 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2226 ttlet lhs_ =
static_cast<decimal
>(lhs);
2227 ttlet rhs_ =
static_cast<decimal
>(rhs);
2228 return datum_impl{lhs_ / rhs_};
2230 }
else if (lhs.is_integer() || rhs.is_integer()) {
2231 ttlet lhs_ =
static_cast<long long int>(lhs);
2232 ttlet rhs_ =
static_cast<long long int>(rhs);
2233 return datum_impl{lhs_ / rhs_};
2235 }
else if (lhs.is_url() && (rhs.is_url() || rhs.is_string())) {
2236 ttlet lhs_ =
static_cast<URL
>(lhs);
2237 ttlet rhs_ =
static_cast<URL
>(rhs);
2238 return datum_impl{lhs_ / rhs_};
2241 throw operation_error(
2242 "Can't divide '/' value {} of type {} by value {} of type {}",
2250 friend datum_impl operator%(datum_impl
const &lhs, datum_impl
const &rhs)
2252 if (lhs.is_float() || rhs.is_float()) {
2253 ttlet lhs_ =
static_cast<double>(lhs);
2254 ttlet rhs_ =
static_cast<double>(rhs);
2255 return datum_impl{
fmod(lhs_, rhs_)};
2257 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2258 ttlet lhs_ =
static_cast<decimal
>(lhs);
2259 ttlet rhs_ =
static_cast<decimal
>(rhs);
2260 return datum_impl{lhs_ % rhs_};
2262 }
else if (lhs.is_integer() || rhs.is_integer()) {
2263 ttlet lhs_ =
static_cast<long long int>(lhs);
2264 ttlet rhs_ =
static_cast<long long int>(rhs);
2265 return datum_impl{lhs_ % rhs_};
2268 throw operation_error(
2269 "Can't take modulo '%' value {} of type {} by value {} of type {}",
2277 friend datum_impl operator<<(datum_impl
const &lhs, datum_impl
const &rhs)
2279 if (lhs.is_integer() && rhs.is_integer()) {
2280 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2281 ttlet rhs_ =
static_cast<int64_t
>(rhs);
2283 return datum_impl{0};
2284 }
else if (rhs_ < 0) {
2286 return datum_impl{lhs_ >> -rhs_};
2287 }
else if (rhs_ == 0) {
2289 }
else if (rhs_ > 63) {
2290 return datum_impl{0};
2292 return datum_impl{lhs_ << rhs_};
2296 throw operation_error(
2297 "Can't logical shift-left '<<' value {} of type {} with value {} of type {}",
2305 friend datum_impl operator>>(datum_impl
const &lhs, datum_impl
const &rhs)
2307 if (lhs.is_integer() && rhs.is_integer()) {
2308 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2309 ttlet rhs_ =
static_cast<int64_t
>(rhs);
2311 return datum_impl{0};
2312 }
else if (rhs_ < 0) {
2313 return datum_impl{lhs_ << -rhs_};
2314 }
else if (rhs_ == 0) {
2316 }
else if (rhs_ > 63) {
2317 return (lhs_ >= 0) ? datum_impl{0} : datum_impl{-1};
2319 return datum_impl{
static_cast<int64_t
>(lhs_) >> rhs_};
2323 throw operation_error(
2324 "Can't arithmetic shift-right '>>' value {} of type {} with value {} of type {}",
2332 friend datum_impl operator&(datum_impl
const &lhs, datum_impl
const &rhs)
2334 if (lhs.is_integer() && rhs.is_integer()) {
2335 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2336 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2337 return datum_impl{lhs_ & rhs_};
2340 throw operation_error(
2341 "Can't AND '&' value {} of type {} with value {} of type {}",
2349 friend datum_impl operator|(datum_impl
const &lhs, datum_impl
const &rhs)
2351 if (lhs.is_integer() && rhs.is_integer()) {
2352 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2353 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2354 return datum_impl{lhs_ | rhs_};
2357 throw operation_error(
2358 "Can't OR '|' value {} of type {} with value {} of type {}",
2366 friend datum_impl operator^(datum_impl
const &lhs, datum_impl
const &rhs)
2368 if (lhs.is_integer() && rhs.is_integer()) {
2369 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2370 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2371 return datum_impl{lhs_ ^ rhs_};
2374 throw operation_error(
2375 "Can't XOR '^' value {} of type {} with value {} of type {}",
2390 return os << static_cast<std::string>(d);
2393 friend void swap(datum_impl &lhs, datum_impl &rhs)
noexcept
2398 friend datum_impl pow(datum_impl
const &lhs, datum_impl
const &rhs)
2400 if (lhs.is_numeric() || rhs.is_numeric()) {
2401 ttlet lhs_ =
static_cast<double>(lhs);
2402 ttlet rhs_ =
static_cast<double>(rhs);
2403 return datum_impl{
std::pow(lhs_, rhs_)};
2406 throw operation_error(
2407 "Can't raise to a power '**' value {} of type {} with value {} of type {}",
2426 if (lhs.is_map() && rhs.is_map()) {
2430 for (
auto rhs_i = rhs.map_begin(); rhs_i != rhs.map_end(); rhs_i++) {
2431 auto result_i = result_map->
find(rhs_i->first);
2432 if (result_i == result_map->end()) {
2433 result_map->insert(*rhs_i);
2435 result_i->second =
deep_merge(result_i->second, rhs_i->second);
2439 }
else if (lhs.is_vector() && rhs.is_vector()) {
2443 for (
auto rhs_i = rhs.vector_begin(); rhs_i != rhs.vector_end(); rhs_i++) {
2454 template<
typename Alternative>
2455 friend bool holds_alternative(
datum_impl const &rhs)
noexcept
2457 if constexpr (std::is_same_v<Alternative, std::string>) {
2458 return rhs.is_string();