119 static constexpr uint64_t
make_string(std::string_view str)
121 ttlet len = str.size();
128 for (uint64_t i = 0; i < len; i++) {
132 return (string_mask + (len << 40)) | x;
141 static uint64_t make_pointer(uint64_t mask,
void *ptr)
143 return mask | (
reinterpret_cast<uint64_t
>(ptr) & pointer_mask);
151 static constexpr uint64_t id_to_mask(uint64_t
id)
164 static constexpr uint16_t make_id(uint16_t
id)
166 return ((
id & 0x10) << 11) | (
id & 0xf) | 0x7ff0;
170 static constexpr int64_t minimum_int = 0xffff'8000'0000'0000LL;
172 static constexpr int64_t maximum_int = 0x0000'7fff'ffff'ffffLL;
174 static constexpr int64_t minimum_mantissa = 0xffff'ff80'0000'0000LL;
175 static constexpr int64_t maximum_mantissa = 0x0000'007f'ffff'ffffLL;
177 static constexpr uint16_t exponent_mask = 0b0111'1111'1111'0000;
178 static constexpr uint64_t pointer_mask = 0x0000'ffff'ffff'ffff;
180 static constexpr uint64_t small_undefined = 0;
181 static constexpr uint64_t small_null = 1;
182 static constexpr uint64_t small_true = 2;
183 static constexpr uint64_t small_false = 3;
184 static constexpr uint64_t small_break = 4;
185 static constexpr uint64_t small_continue = 5;
187 static constexpr uint16_t phy_small_id = make_id(0b00001);
188 static constexpr uint16_t phy_decimal_id = make_id(0b00010);
189 static constexpr uint16_t phy_ymd_id = make_id(0b00011);
190 static constexpr uint16_t phy_integer_id = make_id(0b00100);
191 static constexpr uint16_t phy_string_id = make_id(0b00101);
192 static constexpr uint16_t phy_reserved_id0 = make_id(0b00110);
193 static constexpr uint16_t phy_reserved_id1 = make_id(0b00111);
194 static constexpr uint16_t phy_reserved_id2 = make_id(0b01000);
195 static constexpr uint16_t phy_reserved_id3 = make_id(0b01001);
196 static constexpr uint16_t phy_reserved_id4 = make_id(0b01010);
197 static constexpr uint16_t phy_reserved_id5 = make_id(0b01011);
198 static constexpr uint16_t phy_reserved_id6 = make_id(0b01100);
199 static constexpr uint16_t phy_reserved_id7 = make_id(0b01101);
200 static constexpr uint16_t phy_reserved_id8 = make_id(0b01110);
201 static constexpr uint16_t phy_reserved_id9 = make_id(0b01111);
203 static constexpr uint16_t phy_string_ptr_id = make_id(0b10001);
204 static constexpr uint16_t phy_url_ptr_id = make_id(0b10010);
205 static constexpr uint16_t phy_integer_ptr_id = make_id(0b10011);
206 static constexpr uint16_t phy_vector_ptr_id = make_id(0b10100);
207 static constexpr uint16_t phy_map_ptr_id = make_id(0b10101);
208 static constexpr uint16_t phy_decimal_ptr_id = make_id(0b10110);
209 static constexpr uint16_t phy_bytes_ptr_id = make_id(0b10111);
210 static constexpr uint16_t phy_reserved_ptr_id0 = make_id(0b11000);
211 static constexpr uint16_t phy_reserved_ptr_id1 = make_id(0b11001);
212 static constexpr uint16_t phy_reserved_ptr_id2 = make_id(0b11010);
213 static constexpr uint16_t phy_reserved_ptr_id3 = make_id(0b11011);
214 static constexpr uint16_t phy_reserved_ptr_id4 = make_id(0b11100);
215 static constexpr uint16_t phy_reserved_ptr_id5 = make_id(0b11101);
216 static constexpr uint16_t phy_reserved_ptr_id6 = make_id(0b11110);
217 static constexpr uint16_t phy_reserved_ptr_id7 = make_id(0b11111);
219 static constexpr uint64_t small_mask = id_to_mask(phy_small_id);
220 static constexpr uint64_t undefined_mask = small_mask | small_undefined;
221 static constexpr uint64_t null_mask = small_mask | small_null;
222 static constexpr uint64_t true_mask = small_mask | small_true;
223 static constexpr uint64_t false_mask = small_mask | small_false;
224 static constexpr uint64_t break_mask = small_mask | small_break;
225 static constexpr uint64_t continue_mask = small_mask | small_continue;
226 static constexpr uint64_t string_mask = id_to_mask(phy_string_id);
227 static constexpr uint64_t integer_mask = id_to_mask(phy_integer_id);
228 static constexpr uint64_t decimal_mask = id_to_mask(phy_decimal_id);
229 static constexpr uint64_t ymd_mask = id_to_mask(phy_ymd_id);
230 static constexpr uint64_t string_ptr_mask = id_to_mask(phy_string_ptr_id);
231 static constexpr uint64_t url_ptr_mask = id_to_mask(phy_url_ptr_id);
232 static constexpr uint64_t integer_ptr_mask = id_to_mask(phy_integer_ptr_id);
233 static constexpr uint64_t vector_ptr_mask = id_to_mask(phy_vector_ptr_id);
234 static constexpr uint64_t map_ptr_mask = id_to_mask(phy_map_ptr_id);
235 static constexpr uint64_t decimal_ptr_mask = id_to_mask(phy_decimal_ptr_id);
236 static constexpr uint64_t bytes_ptr_mask = id_to_mask(phy_bytes_ptr_id);
251 uint16_t type_id()
const noexcept
255 return static_cast<uint16_t
>(data >> 48);
258 bool is_phy_float()
const noexcept
260 ttlet
id = type_id();
261 return (
id & 0x7ff0) != 0x7ff0 || (
id & 0x000f) == 0;
264 bool is_phy_integer()
const noexcept
266 return type_id() == phy_integer_id;
269 bool is_phy_string()
const noexcept
271 return type_id() == phy_string_id;
274 bool is_phy_decimal()
const noexcept
276 return type_id() == phy_decimal_id;
279 bool is_phy_ymd()
const noexcept
281 return type_id() == phy_ymd_id;
284 bool is_phy_small()
const noexcept
286 return type_id() == phy_small_id;
289 bool is_phy_pointer()
const noexcept
291 return HasLargeObjects && (type_id() & 0xfff0) == 0xfff0;
294 bool is_phy_string_ptr()
const noexcept
296 return HasLargeObjects && type_id() == phy_string_ptr_id;
299 bool is_phy_url_ptr()
const noexcept
301 return HasLargeObjects && type_id() == phy_url_ptr_id;
304 bool is_phy_integer_ptr()
const noexcept
306 return HasLargeObjects && type_id() == phy_integer_ptr_id;
309 bool is_phy_vector_ptr()
const noexcept
311 return HasLargeObjects && type_id() == phy_vector_ptr_id;
314 bool is_phy_map_ptr()
const noexcept
316 return HasLargeObjects && type_id() == phy_map_ptr_id;
319 bool is_phy_decimal_ptr()
const noexcept
321 return HasLargeObjects && type_id() == phy_decimal_ptr_id;
324 bool is_phy_bytes_ptr()
const noexcept
326 return HasLargeObjects && type_id() == phy_bytes_ptr_id;
331 uint64_t get_unsigned_integer()
const noexcept
333 return (u64 << 16) >> 16;
338 int64_t get_signed_integer()
const noexcept
340 return static_cast<int64_t
>(u64 << 16) >> 16;
348 O *get_pointer()
const
350 return std::launder(
reinterpret_cast<O *
>(get_signed_integer()));
356 void delete_pointer()
noexcept
358 if constexpr (HasLargeObjects) {
360 case phy_integer_ptr_id:
delete get_pointer<int64_t>();
break;
361 case phy_string_ptr_id:
delete get_pointer<std::string>();
break;
362 case phy_url_ptr_id:
delete get_pointer<URL>();
break;
363 case phy_vector_ptr_id:
delete get_pointer<datum_impl::vector>();
break;
364 case phy_map_ptr_id:
delete get_pointer<datum_impl::map>();
break;
365 case phy_decimal_ptr_id:
delete get_pointer<decimal>();
break;
366 case phy_bytes_ptr_id:
delete get_pointer<bstring>();
break;
367 default: tt_no_default();
377 void copy_pointer(
datum_impl const &other)
noexcept
379 if constexpr (HasLargeObjects) {
380 switch (other.type_id()) {
381 case phy_integer_ptr_id: {
382 auto *
const p =
new int64_t(*other.get_pointer<int64_t>());
383 u64 = make_pointer(integer_ptr_mask, p);
386 case phy_string_ptr_id: {
388 u64 = make_pointer(string_ptr_mask, p);
391 case phy_url_ptr_id: {
392 auto *
const p =
new URL(*other.get_pointer<
URL>());
393 u64 = make_pointer(url_ptr_mask, p);
396 case phy_vector_ptr_id: {
398 u64 = make_pointer(vector_ptr_mask, p);
401 case phy_map_ptr_id: {
403 u64 = make_pointer(map_ptr_mask, p);
406 case phy_decimal_ptr_id: {
408 u64 = make_pointer(decimal_ptr_mask, p);
411 case phy_bytes_ptr_id: {
413 u64 = make_pointer(bytes_ptr_mask, p);
416 default: tt_no_default();
433 datum_impl() noexcept : u64(undefined_mask) {}
437 if (is_phy_pointer()) {
438 [[unlikely]] delete_pointer();
442 datum_impl(datum_impl
const &other)
noexcept
444 if (other.is_phy_pointer()) {
445 [[unlikely]] copy_pointer(other);
453 datum_impl &operator=(datum_impl
const &other)
noexcept
455 if (
this != &other) {
456 if (is_phy_pointer()) {
457 [[unlikely]] delete_pointer();
460 if (other.is_phy_pointer()) {
461 [[unlikely]] copy_pointer(other);
471 datum_impl(datum_impl &&other) noexcept : u64(undefined_mask)
475 other.u64 = undefined_mask;
478 datum_impl &operator=(datum_impl &&other)
noexcept
480 if (
this != &other) {
484 other.u64 = undefined_mask;
488 datum_impl(datum_impl::undefined) noexcept : u64(undefined_mask) {}
489 datum_impl(datum_impl::null) noexcept : u64(null_mask) {}
490 datum_impl(datum_impl::_break) noexcept : u64(break_mask) {}
491 datum_impl(datum_impl::_continue) noexcept : u64(continue_mask) {}
493 datum_impl(
double value) noexcept : f64(value)
495 if (value != value) {
496 u64 = undefined_mask;
499 datum_impl(
float value) noexcept : datum_impl(
static_cast<double>(value)) {}
501 datum_impl(decimal value)
noexcept
503 long long m = value.mantissa();
505 if (m < minimum_mantissa || m > maximum_mantissa) {
506 [[unlikely]]
if constexpr (HasLargeObjects)
508 auto *
const p =
new decimal(value);
509 u64 = make_pointer(decimal_ptr_mask, p);
516 int e = value.exponent();
518 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
522 datum_impl(date::year_month_day
const &ymd) noexcept :
524 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
525 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
526 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
527 0x0000ffff'ffffffff))
531 datum_impl(
unsigned long long value) noexcept : u64(integer_mask | value)
533 if (value > maximum_int) {
534 [[unlikely]]
if constexpr (HasLargeObjects)
536 auto *
const p =
new uint64_t(value);
537 u64 = make_pointer(integer_ptr_mask, p);
541 throw std::overflow_error(fmt::format(
"Constructing datum from integer {}, larger than {}", value, maximum_int));
545 datum_impl(
unsigned long value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
546 datum_impl(
unsigned int value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
547 datum_impl(
unsigned short value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
548 datum_impl(
unsigned char value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
550 datum_impl(
signed long long value) noexcept : u64(integer_mask | (
static_cast<uint64_t
>(value) & 0x0000ffff'ffffffff))
552 if (value < minimum_int || value > maximum_int)
555 if constexpr (HasLargeObjects) {
556 auto *
const p =
new int64_t(value);
557 u64 = make_pointer(integer_ptr_mask, p);
560 "Constructing integer {} to datum, outside {} and {}", value, minimum_int, maximum_int));
564 datum_impl(
signed long value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
565 datum_impl(
signed int value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
566 datum_impl(
signed short value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
567 datum_impl(
signed char value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
569 datum_impl(
bool value) noexcept : u64(value ? true_mask : false_mask) {}
570 datum_impl(
char value) noexcept : u64(string_mask | (uint64_t{1} << 40) | value) {}
572 datum_impl(std::string_view value) noexcept : u64(make_string(value))
575 if constexpr (HasLargeObjects) {
577 u64 = make_pointer(string_ptr_mask, p);
579 throw std::overflow_error(fmt::format(
"Constructing string {} to datum, larger than 6 characters", value));
584 datum_impl(
std::string const &value) noexcept : datum_impl(std::string_view(value)) {}
585 datum_impl(
char const *value) noexcept : datum_impl(std::string_view(value)) {}
587 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
588 datum_impl(URL
const &value)
noexcept
590 auto *
const p =
new URL(value);
591 u64 = make_pointer(url_ptr_mask, p);
594 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
595 datum_impl(URL &&value)
noexcept
597 auto *
const p =
new URL(
std::move(value));
598 u64 = make_pointer(url_ptr_mask, p);
601 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
602 datum_impl(datum_impl::vector
const &value)
noexcept
604 auto *
const p =
new datum_impl::vector(value);
605 u64 = make_pointer(vector_ptr_mask, p);
608 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
609 datum_impl(datum_impl::vector &&value)
noexcept
611 auto *
const p =
new datum_impl::vector(
std::move(value));
612 u64 = make_pointer(vector_ptr_mask, p);
615 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
616 datum_impl(datum_impl::map
const &value)
noexcept
618 auto *
const p =
new datum_impl::map(value);
619 u64 = make_pointer(map_ptr_mask, p);
622 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
623 datum_impl(datum_impl::map &&value)
noexcept
625 auto *
const p =
new datum_impl::map(
std::move(value));
626 u64 = make_pointer(map_ptr_mask, p);
629 datum_impl &operator=(datum_impl::undefined rhs)
noexcept
631 if (is_phy_pointer()) {
632 [[unlikely]] delete_pointer();
634 u64 = undefined_mask;
638 datum_impl &operator=(datum_impl::null rhs)
noexcept
640 if (is_phy_pointer()) {
641 [[unlikely]] delete_pointer();
647 datum_impl &operator=(datum_impl::_break rhs)
noexcept
649 if (is_phy_pointer()) {
650 [[unlikely]] delete_pointer();
656 datum_impl &operator=(datum_impl::_continue rhs)
noexcept
658 if (is_phy_pointer()) {
659 [[unlikely]] delete_pointer();
665 datum_impl &operator=(
double rhs)
noexcept
667 if (is_phy_pointer()) {
668 [[unlikely]] delete_pointer();
674 u64 = undefined_mask;
678 datum_impl &operator=(
float rhs)
noexcept
680 return *
this =
static_cast<double>(rhs);
683 datum_impl &operator=(decimal rhs)
noexcept
685 if (is_phy_pointer()) {
686 [[unlikely]] delete_pointer();
689 long long m = rhs.mantissa();
690 if (m < minimum_mantissa || m > maximum_mantissa) {
691 [[unlikely]]
if constexpr (HasLargeObjects)
693 auto *
const p =
new decimal(rhs);
694 u64 = make_pointer(decimal_ptr_mask, p);
701 int e = rhs.exponent();
703 u64 = decimal_mask |
static_cast<uint8_t
>(e) | ((
static_cast<uint64_t
>(m) << 24) >> 16);
708 datum_impl &operator=(date::year_month_day
const &ymd)
noexcept
710 if (is_phy_pointer()) {
711 [[unlikely]] delete_pointer();
715 (((
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
716 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
717 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))) &
718 0x0000ffff'ffffffff);
722 datum_impl &operator=(
unsigned long long rhs)
724 if (is_phy_pointer()) {
725 [[unlikely]] delete_pointer();
728 u64 = integer_mask |
static_cast<uint64_t
>(rhs);
729 if (rhs > maximum_int) {
730 [[unlikely]]
if constexpr (HasLargeObjects)
732 auto *
const p =
new uint64_t(rhs);
733 u64 = make_pointer(integer_ptr_mask, p);
737 throw std::overflow_error(fmt::format(
"Assigning integer {} to datum, larger than {}", rhs, maximum_int));
742 datum_impl &operator=(
unsigned long rhs)
noexcept
744 return *
this =
static_cast<unsigned long long>(rhs);
746 datum_impl &operator=(
unsigned int rhs)
noexcept
748 return *
this =
static_cast<unsigned long long>(rhs);
750 datum_impl &operator=(
unsigned short rhs)
noexcept
752 return *
this =
static_cast<unsigned long long>(rhs);
754 datum_impl &operator=(
unsigned char rhs)
noexcept
756 return *
this =
static_cast<unsigned long long>(rhs);
759 datum_impl &operator=(
signed long long rhs)
noexcept
761 if (is_phy_pointer()) {
762 [[unlikely]] delete_pointer();
765 u64 = integer_mask | (
static_cast<uint64_t
>(rhs) & 0x0000ffff'ffffffff);
766 if (rhs < minimum_int || rhs > maximum_int) {
767 [[unlikely]]
if constexpr (HasLargeObjects)
769 auto *
const p =
new int64_t(rhs);
770 u64 = make_pointer(integer_ptr_mask, p);
774 throw std::overflow_error(fmt::format(
"Assigning integer {} to datum, outside {} and {}", rhs, minimum_int, maximum_int));
780 datum_impl &operator=(
signed long rhs)
noexcept
782 return *
this =
static_cast<signed long long>(rhs);
784 datum_impl &operator=(
signed int rhs)
noexcept
786 return *
this =
static_cast<signed long long>(rhs);
788 datum_impl &operator=(
signed short rhs)
noexcept
790 return *
this =
static_cast<signed long long>(rhs);
792 datum_impl &operator=(
signed char rhs)
noexcept
794 return *
this =
static_cast<signed long long>(rhs);
797 datum_impl &operator=(
bool rhs)
noexcept
799 if (is_phy_pointer()) {
800 [[unlikely]] delete_pointer();
802 u64 = rhs ? true_mask : false_mask;
806 datum_impl &operator=(
char rhs)
noexcept
808 if (is_phy_pointer()) {
809 [[unlikely]] delete_pointer();
811 u64 = string_mask | (uint64_t{1} << 40) |
static_cast<uint64_t
>(rhs);
815 datum_impl &operator=(std::string_view rhs)
817 if (is_phy_pointer()) {
818 [[unlikely]] delete_pointer();
821 u64 = make_string(rhs);
823 if constexpr (HasLargeObjects) {
825 u64 = make_pointer(string_ptr_mask, p);
827 throw std::overflow_error(fmt::format(
"Assigning string {} to datum, larger than 6 characters", rhs));
835 *
this = std::string_view{rhs};
839 datum_impl &operator=(
char const *rhs)
841 *
this = std::string_view{rhs};
845 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
846 datum_impl &operator=(URL
const &rhs)
noexcept
848 if (is_phy_pointer()) {
849 [[unlikely]] delete_pointer();
852 auto *
const p =
new URL(rhs);
853 u64 = make_pointer(url_ptr_mask, p);
857 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
858 datum_impl &operator=(URL &&rhs)
noexcept
860 if (is_phy_pointer()) {
861 [[unlikely]] delete_pointer();
865 u64 = make_pointer(url_ptr_mask, p);
869 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
870 datum_impl &operator=(datum_impl::vector
const &rhs)
872 if (is_phy_pointer()) {
873 [[unlikely]] delete_pointer();
876 auto *
const p =
new datum_impl::vector(rhs);
877 u64 = make_pointer(vector_ptr_mask, p);
882 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
883 datum_impl &operator=(datum_impl::vector &&rhs)
885 if (is_phy_pointer()) {
886 [[unlikely]] delete_pointer();
889 auto *
const p =
new datum_impl::vector(
std::move(rhs));
890 u64 = make_pointer(vector_ptr_mask, p);
895 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
896 datum_impl &operator=(datum_impl::map
const &rhs)
898 if (is_phy_pointer()) {
899 [[unlikely]] delete_pointer();
902 auto *
const p =
new datum_impl::map(rhs);
903 u64 = make_pointer(map_ptr_mask, p);
908 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
909 datum_impl &operator=(datum_impl::map &&rhs)
911 if (is_phy_pointer()) {
912 [[unlikely]] delete_pointer();
915 auto *
const p =
new datum_impl::map(
std::move(rhs));
916 u64 = make_pointer(map_ptr_mask, p);
921 explicit operator double()
const
923 if (is_phy_float()) {
925 }
else if (is_decimal()) {
926 return static_cast<double>(
static_cast<decimal
>(*this));
927 }
else if (is_phy_integer()) {
928 return static_cast<double>(get_signed_integer());
929 }
else if (is_phy_integer_ptr()) {
930 return static_cast<double>(*get_pointer<int64_t>());
932 throw operation_error(
933 "Value {} of type {} can not be converted to a double", this->repr(), this->type_name());
937 explicit operator float()
const
939 return static_cast<float>(
static_cast<double>(*this));
942 explicit operator decimal()
const
944 if (is_phy_decimal()) {
945 uint64_t v = get_unsigned_integer();
946 int e =
static_cast<int8_t
>(v);
947 long long m =
static_cast<int64_t
>(v << 16) >> 24;
948 return decimal{e, m};
949 }
else if (is_phy_decimal_ptr()) {
950 return *get_pointer<decimal>();
951 }
else if (is_phy_integer() || is_phy_integer_ptr()) {
952 return decimal{
static_cast<signed long long>(*this)};
953 }
else if (is_phy_float()) {
954 return decimal{
static_cast<double>(*this)};
956 throw operation_error(
957 "Value {} of type {} can not be converted to a decimal", this->repr(), this->type_name());
961 explicit operator date::year_month_day()
const
964 ttlet u = get_unsigned_integer();
965 ttlet i = get_signed_integer();
966 ttlet day =
static_cast<unsigned>(u & 0x1f);
967 ttlet month =
static_cast<unsigned>((u >> 5) & 0xf);
968 ttlet year =
static_cast<signed>(i >> 9);
971 throw operation_error(
972 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
975 throw operation_error(
976 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
978 return date::year_month_day{date::year{year}, date::month{month}, date::day{day}};
980 throw operation_error(
981 "Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
985 explicit operator signed long long()
const
987 if (is_phy_integer()) {
988 return get_signed_integer();
989 }
else if (is_phy_integer_ptr()) {
990 return *get_pointer<signed long long>();
991 }
else if (is_phy_float()) {
992 return static_cast<signed long long>(f64);
993 }
else if (is_phy_small()) {
994 switch (get_unsigned_integer()) {
995 case small_true:
return 1;
996 case small_false:
return 0;
999 throw operation_error(
1000 "Value {} of type {} can not be converted to a signed long long", this->repr(), this->type_name());
1003 explicit operator signed long()
const
1005 ttlet v =
static_cast<signed long long>(*this);
1007 throw operation_error(
1008 "Value {} of type {} can not be converted to a signed long", this->repr(), this->type_name());
1010 return static_cast<signed long>(v);
1013 explicit operator signed int()
const
1015 ttlet v =
static_cast<signed long long>(*this);
1017 throw operation_error(
1018 "Value {} of type {} can not be converted to a signed int", this->repr(), this->type_name());
1020 return static_cast<signed int>(v);
1023 explicit operator signed short()
const
1025 ttlet v =
static_cast<signed long long>(*this);
1027 throw operation_error(
1028 "Value {} of type {} can not be converted to a signed short", this->repr(), this->type_name());
1030 return static_cast<signed short>(v);
1033 explicit operator signed char()
const
1035 ttlet v =
static_cast<int64_t
>(*this);
1037 throw operation_error(
1038 "Value {} of type {} can not be converted to a signed char", this->repr(), this->type_name());
1040 return static_cast<signed char>(v);
1043 explicit operator unsigned long long()
const
1045 ttlet v =
static_cast<signed long long>(*this);
1047 throw operation_error(
1048 "Value {} of type {} can not be converted to a unsigned long long", this->repr(), this->type_name());
1050 return static_cast<unsigned long long>(v);
1053 explicit operator unsigned long()
const
1055 ttlet v =
static_cast<unsigned long long>(*this);
1057 throw operation_error(
1058 "Value {} of type {} can not be converted to a unsigned long", this->repr(), this->type_name());
1060 return static_cast<unsigned long>(v);
1063 explicit operator unsigned int()
const
1065 ttlet v =
static_cast<unsigned long long>(*this);
1067 throw operation_error(
1068 "Value {} of type {} can not be converted to a unsigned int", this->repr(), this->type_name());
1070 return static_cast<unsigned int>(v);
1073 explicit operator unsigned short()
const
1075 ttlet v =
static_cast<unsigned long long>(*this);
1077 throw operation_error(
1078 "Value {} of type {} can not be converted to a unsigned short", this->repr(), this->type_name());
1080 return static_cast<unsigned short>(v);
1083 explicit operator unsigned char()
const
1085 ttlet v =
static_cast<unsigned long long>(*this);
1087 throw operation_error(
1088 "Value {} of type {} can not be converted to a unsigned char", this->repr(), this->type_name());
1090 return static_cast<unsigned char>(v);
1093 explicit operator bool() const noexcept
1095 switch (type_id()) {
1096 case phy_small_id:
return get_unsigned_integer() == small_true;
1097 case phy_integer_id:
return static_cast<int64_t
>(*this) != 0;
1098 case phy_decimal_id:
return static_cast<decimal
>(*this) != 0;
1099 case phy_ymd_id:
return true;
1100 case phy_integer_ptr_id:
return *get_pointer<int64_t>() != 0;
1102 case phy_string_ptr_id:
return this->size() > 0;
1103 case phy_url_ptr_id:
return true;
1104 case phy_vector_ptr_id:
return this->size() > 0;
1105 case phy_map_ptr_id:
return this->size() > 0;
1106 case phy_decimal_ptr_id:
return static_cast<decimal
>(*this) != 0;
1107 case phy_bytes_ptr_id:
return this->size() > 0;
1109 if (is_phy_float()) {
1110 return static_cast<double>(*this) != 0.0;
1117 explicit operator char()
const
1119 if (is_phy_string() && size() == 1) {
1121 }
else if (is_phy_string_ptr() && size() == 1) {
1122 return get_pointer<std::string>()->at(0);
1124 throw operation_error(
1125 "Value {} of type {} can not be converted to a char", this->repr(), this->type_name());
1129 explicit operator bstring()
const
1132 if constexpr (HasLargeObjects) {
1133 return *get_pointer<bstring>();
1138 throw operation_error(
1139 "Value {} of type {} can not be converted to bytes", this->repr(), this->type_name());
1145 switch (type_id()) {
1147 switch (get_unsigned_integer()) {
1148 case small_undefined:
return "undefined";
1149 case small_null:
return "null";
1150 case small_true:
return "true";
1151 case small_false:
return "false";
1152 case small_break:
return "break";
1153 case small_continue:
return "continue";
1154 default: tt_no_default();
1157 case phy_integer_id:
return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1158 case phy_decimal_id:
return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1159 case phy_ymd_id:
return fmt::format(
"{}",
static_cast<date::year_month_day
>(*
this));
1160 case phy_integer_ptr_id:
1161 if constexpr (HasLargeObjects) {
1162 return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1167 case phy_string_id: {
1168 ttlet length = size();
1170 for (
int i = 0; i < length; i++) {
1171 buffer[i] = (u64 >> ((length - i - 1) * 8)) & 0xff;
1176 case phy_string_ptr_id:
1177 if constexpr (HasLargeObjects) {
1178 return *get_pointer<std::string>();
1183 case phy_url_ptr_id:
1184 if constexpr (HasLargeObjects) {
1185 return to_string(*get_pointer<URL>());
1190 case phy_decimal_ptr_id:
1191 if constexpr (HasLargeObjects) {
1192 return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1197 case phy_vector_ptr_id:
1198 if constexpr (HasLargeObjects) {
1201 for (
auto i = vector_begin(); i != vector_end(); i++) {
1213 case phy_map_ptr_id:
1214 if constexpr (HasLargeObjects) {
1219 return a.first < b.first;
1224 for (
auto &item : items) {
1228 r += item.first.repr();
1230 r += item.second.repr();
1238 case phy_bytes_ptr_id:
1239 if constexpr (HasLargeObjects) {
1246 if (is_phy_float()) {
1247 auto str = fmt::format(
"{:g}",
static_cast<double>(*
this));
1248 if (str.find(
'.') == str.npos) {
1258 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1259 explicit operator URL()
const
1263 }
else if (is_url()) {
1264 return *get_pointer<URL>();
1266 throw operation_error(
1267 "Value {} of type {} can not be converted to a URL", this->repr(), this->type_name());
1271 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1272 explicit operator datum_impl::vector()
const
1275 return *get_pointer<datum_impl::vector>();
1277 throw operation_error(
1278 "Value {} of type {} can not be converted to a Vector", this->repr(), this->type_name());
1282 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1283 explicit operator datum_impl::map()
const
1286 return *get_pointer<datum_impl::map>();
1288 throw operation_error(
1289 "Value {} of type {} can not be converted to a Map", this->repr(), this->type_name());
1300 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1303 if (is_undefined()) {
1306 u64 = map_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1310 auto &m = *get_pointer<datum_impl::map>();
1311 auto [i, did_insert] = m.try_emplace(rhs);
1314 }
else if (is_vector() && rhs.is_integer()) {
1315 auto index =
static_cast<int64_t
>(rhs);
1316 auto &v = *get_pointer<datum_impl::vector>();
1319 index = std::ssize(v) + index;
1322 if (index < 0 || index >= std::ssize(v)) {
1324 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1330 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1341 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1345 ttlet &m = *get_pointer<datum_impl::map>();
1346 ttlet i = m.find(rhs);
1347 if (i == m.cend()) {
1348 throw operation_error(
"Could not find key {} in map of size {}", rhs.repr(), std::ssize(m));
1352 }
else if (is_vector() && rhs.is_integer()) {
1353 auto index =
static_cast<int64_t
>(rhs);
1354 ttlet &v = *get_pointer<datum_impl::vector>();
1357 index = std::ssize(v) + index;
1360 if (index < 0 || index >= std::ssize(v)) {
1362 "Index {} out of range to access value in vector of size {}", index, std::ssize(v));
1368 "Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1380 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1384 ttlet &m = *get_pointer<datum_impl::map>();
1385 ttlet i = m.find(rhs);
1386 return i != m.cend();
1388 }
else if (is_vector() && rhs.is_integer()) {
1389 auto index =
static_cast<int64_t
>(rhs);
1390 ttlet &v = *get_pointer<datum_impl::vector>();
1393 index = std::ssize(v) + index;
1396 return index >= 0 && index < std::ssize(v);
1408 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1411 if (is_undefined()) {
1414 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1418 auto *v = get_pointer<datum_impl::vector>();
1423 throw operation_error(
"Cannot append new item onto type {}", type_name());
1427 template<
typename... Args>
1428 void emplace_back(Args &&... args)
1430 if (is_undefined()) {
1433 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1437 auto *v = get_pointer<datum_impl::vector>();
1438 v->emplace_back(std::forward<Args>(args)...);
1441 throw operation_error(
"Cannot append new item onto type {}", type_name());
1445 template<
typename Arg>
1446 void push_back(Arg &&arg)
1448 if (is_undefined()) {
1450 auto *p =
new datum_impl::vector();
1451 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1455 auto *v = get_pointer<datum_impl::vector>();
1456 v->push_back(std::forward<Arg>(arg));
1459 throw operation_error(
"Cannot append new item onto type {}", type_name());
1466 auto *v = get_pointer<datum_impl::vector>();
1470 throw operation_error(
"Cannot pop_back() onto type {}", type_name());
1474 datum_impl year()
const
1477 return {
static_cast<signed>(
static_cast<date::year_month_day
>(*this).year())};
1479 throw operation_error(
"Cannot get year() from type {}", type_name());
1483 datum_impl quarter()
const
1486 auto month =
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month());
1487 return {((month - 1) / 3) + 1};
1489 throw operation_error(
"Cannot get month() from type {}", type_name());
1493 datum_impl month()
const
1496 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month())};
1498 throw operation_error(
"Cannot get month() from type {}", type_name());
1502 datum_impl day()
const
1505 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).day())};
1507 throw operation_error(
"Cannot get day() from type {}", type_name());
1511 datum_impl
const &front()
const
1514 ttlet *v = get_pointer<datum_impl::vector>();
1518 throw operation_error(
"Cannot front() onto type {}", type_name());
1525 auto *v = get_pointer<datum_impl::vector>();
1529 throw operation_error(
"Cannot front() onto type {}", type_name());
1533 datum_impl
const &back()
const
1536 ttlet *v = get_pointer<datum_impl::vector>();
1540 throw operation_error(
"Cannot back() onto type {}", type_name());
1547 auto *v = get_pointer<datum_impl::vector>();
1551 throw operation_error(
"Cannot back() onto type {}", type_name());
1557 switch (type_id()) {
1559 switch (get_unsigned_integer()) {
1560 case small_undefined:
return "undefined";
1561 case small_null:
return "null";
1562 case small_true:
return "true";
1563 case small_false:
return "false";
1564 case small_break:
return "break";
1565 case small_continue:
return "continue";
1566 default: tt_no_default();
1568 case phy_integer_id:
1569 case phy_integer_ptr_id:
return static_cast<std::string>(*this);
1570 case phy_decimal_id:
1571 case phy_decimal_ptr_id:
return static_cast<std::string>(*this);
1572 case phy_ymd_id:
return static_cast<std::string>(*this);
1574 case phy_string_ptr_id:
return fmt::format(
"\"{}\"",
static_cast<std::string>(*
this));
1575 case phy_url_ptr_id:
return fmt::format(
"<URL {}>",
static_cast<std::string>(*
this));
1576 case phy_vector_ptr_id:
return static_cast<std::string>(*this);
1577 case phy_map_ptr_id:
return static_cast<std::string>(*this);
1578 case phy_bytes_ptr_id:
return static_cast<std::string>(*this);
1580 if (is_phy_float()) {
1595 return phy_integer_id;
1603 if (key.
size() > 0 && is_map()) {
1604 ttlet index = key.
at(0);
1605 auto &next = (*this)[index];
1607 return next.get_by_path(next_key);
1609 }
else if (key.
size() > 0 && is_vector()) {
1611 auto &
next = (*this)[index];
1613 return next.get_by_path(next_key);
1615 }
else if (key.
size() > 0) {
1616 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1624 if (key.
size() > 0 && is_map()) {
1625 ttlet index = key.
at(0);
1626 ttlet
next = (*this)[index];
1629 }
else if (key.
size() > 0 && is_vector()) {
1631 ttlet
next = (*this)[index];
1634 }
else if (key.
size() > 0) {
1635 throw operation_error(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1641 bool is_integer() const noexcept
1643 return is_phy_integer() || is_phy_integer_ptr();
1645 bool is_decimal() const noexcept
1647 return is_phy_decimal() || is_phy_decimal_ptr();
1649 bool is_ymd() const noexcept
1651 return is_phy_ymd();
1653 bool is_float() const noexcept
1655 return is_phy_float();
1657 bool is_string() const noexcept
1659 return is_phy_string() || is_phy_string_ptr();
1661 bool is_bytes() const noexcept
1663 return is_phy_bytes_ptr();
1666 bool is_bool() const noexcept
1668 if (is_phy_small()) {
1669 ttlet tmp = get_unsigned_integer();
1670 return tmp == small_true || tmp == small_false;
1676 bool is_null() const noexcept
1678 return is_phy_small() && get_unsigned_integer() == small_null;
1681 bool is_undefined() const noexcept
1683 return is_phy_small() && get_unsigned_integer() == small_undefined;
1686 bool is_break() const noexcept
1688 return is_phy_small() && get_unsigned_integer() == small_break;
1691 bool is_continue() const noexcept
1693 return is_phy_small() && get_unsigned_integer() == small_continue;
1695 bool is_url() const noexcept
1697 return is_phy_url_ptr();
1700 bool is_vector() const noexcept
1702 return is_phy_vector_ptr();
1704 bool is_map() const noexcept
1706 return is_phy_map_ptr();
1708 bool is_numeric() const noexcept
1710 return is_integer() || is_decimal() || is_float();
1713 datum_type_t type() const noexcept
1715 switch (type_id()) {
1717 switch (get_unsigned_integer()) {
1718 case small_undefined:
return datum_type_t::Undefined;
1719 case small_null:
return datum_type_t::Null;
1720 case small_false:
return datum_type_t::Boolean;
1721 case small_true:
return datum_type_t::Boolean;
1722 case small_break:
return datum_type_t::Break;
1723 case small_continue:
return datum_type_t::Continue;
1724 default: tt_no_default();
1727 case phy_integer_id:
1728 case phy_integer_ptr_id:
return datum_type_t::Integer;
1729 case phy_decimal_id:
1730 case phy_decimal_ptr_id:
return datum_type_t::Decimal;
1731 case phy_ymd_id:
return datum_type_t::YearMonthDay;
1733 case phy_string_ptr_id:
return datum_type_t::String;
1734 case phy_url_ptr_id:
return datum_type_t::URL;
1735 case phy_vector_ptr_id:
return datum_type_t::Vector;
1736 case phy_map_ptr_id:
return datum_type_t::Map;
1737 case phy_bytes_ptr_id:
return datum_type_t::Bytes;
1739 if (is_phy_float()) {
1740 return datum_type_t::Float;
1747 char const *type_name() const noexcept
1749 switch (type_id()) {
1751 switch (get_unsigned_integer()) {
1752 case small_undefined:
return "Undefined";
1753 case small_null:
return "Null";
1754 case small_false:
return "Boolean";
1755 case small_true:
return "Boolean";
1756 case small_break:
return "Break";
1757 case small_continue:
return "Continue";
1758 default: tt_no_default();
1761 case phy_integer_id:
1762 case phy_integer_ptr_id:
return "Integer";
1763 case phy_decimal_id:
1764 case phy_decimal_ptr_id:
return "Decimal";
1765 case phy_ymd_id:
return "YearMonthDay";
1767 case phy_string_ptr_id:
return "String";
1768 case phy_url_ptr_id:
return "URL";
1769 case phy_vector_ptr_id:
return "Vector";
1770 case phy_map_ptr_id:
return "Map";
1771 case phy_bytes_ptr_id:
return "Bytes";
1773 if (is_phy_float()) {
1783 switch (type_id()) {
1784 case phy_string_id:
return (u64 >> 40) & 0xff;
1785 case phy_string_ptr_id:
return get_pointer<std::string>()->size();
1786 case phy_vector_ptr_id:
return get_pointer<datum_impl::vector>()->size();
1787 case phy_map_ptr_id:
return get_pointer<datum_impl::map>()->size();
1788 case phy_bytes_ptr_id:
return get_pointer<bstring>()->size();
1789 default:
throw operation_error(
"Can't get size of value {} of type {}.", this->repr(), this->type_name());
1793 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1794 typename map::const_iterator map_begin()
const
1796 if (is_phy_map_ptr()) {
1797 return get_pointer<datum_impl::map>()->begin();
1799 throw operation_error(
"map_begin() expect datum to be a map, but it is a {}.", this->type_name());
1803 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1804 typename map::const_iterator map_end()
const
1806 if (is_phy_map_ptr()) {
1807 return get_pointer<datum_impl::map>()->end();
1809 throw operation_error(
"map_end() expect datum to be a map, but it is a {}.", this->type_name());
1813 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1814 typename vector::const_iterator vector_begin()
const
1816 if (is_phy_vector_ptr()) {
1817 return get_pointer<datum_impl::vector>()->begin();
1819 throw operation_error(
1820 "vector_begin() expect datum to be a vector, but it is a {}.", this->type_name());
1824 template<
bool P = HasLargeObjects, std::enable_if_t<P,
int> = 0>
1825 typename vector::const_iterator vector_end()
const
1827 if (is_phy_vector_ptr()) {
1828 return get_pointer<datum_impl::vector>()->end();
1830 throw operation_error(
"vector_end() expect datum to be a vector, but it is a {}.", this->type_name());
1834 size_t hash() const noexcept
1836 if (is_phy_float()) {
1838 }
else if (is_phy_pointer()) {
1839 [[unlikely]]
switch (type_id())
1842 case phy_url_ptr_id:
return std::hash<URL>{}(*get_pointer<URL>());
1843 case phy_vector_ptr_id:
1844 return std::accumulate(vector_begin(), vector_end(),
size_t{0}, [](
size_t a,
auto x) {
1845 return a ^ x.hash();
1847 case phy_map_ptr_id:
1848 return std::accumulate(map_begin(), map_end(),
size_t{0}, [](
size_t a,
auto x) {
1849 return a ^ (x.first.hash() ^ x.second.hash());
1853 default: tt_no_default();
1860 datum_impl &operator++()
1862 if (!this->is_numeric()) {
1863 throw operation_error(
"Can't increment '++' value {} of type {}", this->repr(), this->type_name());
1869 datum_impl &operator--()
1871 if (!this->is_numeric()) {
1872 throw operation_error(
"Can't increment '--' value {} of type {}", this->repr(), this->type_name());
1878 datum_impl operator++(
int)
1885 datum_impl operator--(
int)
1892 datum_impl &operator+=(datum_impl
const &rhs)
1894 if (this->is_vector()) {
1895 this->push_back(rhs);
1897 *
this = *
this + rhs;
1902 datum_impl &operator-=(datum_impl
const &rhs)
1904 return *
this = *
this - rhs;
1907 datum_impl &operator*=(datum_impl
const &rhs)
1909 return *
this = *
this * rhs;
1912 datum_impl &operator/=(datum_impl
const &rhs)
1914 return *
this = *
this / rhs;
1917 datum_impl &operator%=(datum_impl
const &rhs)
1919 return *
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 friend datum_impl operator~(datum_impl
const &rhs)
1949 if (rhs.is_integer()) {
1950 return datum_impl{~static_cast<int64_t>(rhs)};
1952 throw operation_error(
"Can't bit-wise negate '~' value {} of type {}", rhs.repr(), rhs.type_name());
1956 friend datum_impl operator-(datum_impl
const &rhs)
1958 if (rhs.is_integer()) {
1959 return datum_impl{-
static_cast<int64_t
>(rhs)};
1960 }
else if (rhs.is_decimal()) {
1961 return datum_impl{-
static_cast<decimal
>(rhs)};
1962 }
else if (rhs.is_float()) {
1963 return datum_impl{-
static_cast<double>(rhs)};
1965 throw operation_error(
"Can't arithmetic negate '-' value {} of type {}", rhs.repr(), rhs.type_name());
1969 friend datum_impl operator+(datum_impl
const &rhs)
1971 if (rhs.is_numeric()) {
1974 throw operation_error(
"Can't arithmetic posgate '+' value {} of type {}", rhs.repr(), rhs.type_name());
1978 friend bool operator==(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
1980 switch (lhs.type_id()) {
1981 case datum_impl::phy_small_id:
return rhs.is_phy_small() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1982 case datum_impl::phy_integer_id:
1983 case datum_impl::phy_integer_ptr_id:
1985 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1986 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1987 (rhs.is_integer() &&
static_cast<int64_t
>(lhs) ==
static_cast<int64_t
>(rhs)));
1988 case datum_impl::phy_decimal_id:
1989 case datum_impl::phy_decimal_ptr_id:
1991 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1992 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1993 (rhs.is_integer() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)));
1994 case datum_impl::phy_ymd_id:
return rhs.is_ymd() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1995 case datum_impl::phy_string_id:
1996 case datum_impl::phy_string_ptr_id:
1999 (rhs.is_url() &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs)));
2000 case datum_impl::phy_url_ptr_id:
2001 return (rhs.is_url() || rhs.is_string()) &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs);
2002 case datum_impl::phy_vector_ptr_id:
2003 return rhs.is_vector() && *lhs.get_pointer<datum_impl::vector>() == *rhs.get_pointer<datum_impl::vector>();
2004 case datum_impl::phy_map_ptr_id:
2005 return rhs.is_map() && *lhs.get_pointer<datum_impl::map>() == *rhs.get_pointer<datum_impl::map>();
2006 case datum_impl::phy_bytes_ptr_id:
return (rhs.is_bytes() &&
static_cast<bstring
>(lhs) ==
static_cast<bstring
>(rhs));
2008 if (lhs.is_phy_float()) {
2009 return rhs.is_numeric() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs);
2016 friend bool operator<(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2018 switch (lhs.type_id()) {
2019 case datum_impl::phy_small_id:
2020 if (lhs.is_bool() && rhs.is_bool()) {
2021 return static_cast<bool>(lhs) <
static_cast<bool>(rhs);
2023 return lhs.get_unsigned_integer() < rhs.get_unsigned_integer();
2025 case datum_impl::phy_integer_id:
2026 case datum_impl::phy_integer_ptr_id:
2027 if (rhs.is_float()) {
2028 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2029 }
else if (rhs.is_decimal()) {
2030 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2031 }
else if (rhs.is_integer()) {
2032 return static_cast<int64_t
>(lhs) <
static_cast<int64_t
>(rhs);
2034 return lhs.type_order() < rhs.type_order();
2036 case datum_impl::phy_decimal_id:
2037 case datum_impl::phy_decimal_ptr_id:
2038 if (rhs.is_float()) {
2039 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2040 }
else if (rhs.is_decimal()) {
2041 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2042 }
else if (rhs.is_integer()) {
2043 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
2045 return lhs.type_order() < rhs.type_order();
2047 case datum_impl::phy_ymd_id:
2049 return static_cast<date::year_month_day
>(lhs) <
static_cast<date::year_month_day
>(rhs);
2051 return lhs.type_order() < rhs.type_order();
2053 case datum_impl::phy_string_id:
2054 case datum_impl::phy_string_ptr_id:
2055 if (rhs.is_string()) {
2057 }
else if (rhs.is_url()) {
2058 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2060 return lhs.type_order() < rhs.type_order();
2062 case datum_impl::phy_url_ptr_id:
2063 if (rhs.is_url() || rhs.is_string()) {
2064 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
2066 return lhs.type_order() < rhs.type_order();
2068 case datum_impl::phy_vector_ptr_id:
2069 if (rhs.is_vector()) {
2070 return *lhs.get_pointer<datum_impl::vector>() < *rhs.get_pointer<datum_impl::vector>();
2072 return lhs.type_order() < rhs.type_order();
2074 case datum_impl::phy_map_ptr_id:
2076 return *lhs.get_pointer<datum_impl::map>() < *rhs.get_pointer<datum_impl::map>();
2078 return lhs.type_order() < rhs.type_order();
2080 case datum_impl::phy_bytes_ptr_id:
2081 if (rhs.is_bytes()) {
2082 return static_cast<bstring
>(lhs) <
static_cast<bstring
>(rhs);
2084 return lhs.type_order() < rhs.type_order();
2087 if (lhs.is_phy_float()) {
2088 if (rhs.is_numeric()) {
2089 return static_cast<double>(lhs) <
static_cast<double>(rhs);
2091 return lhs.type_order() < rhs.type_order();
2099 friend bool operator!=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2101 return !(lhs == rhs);
2104 friend bool operator>(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2109 friend bool operator<=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2111 return !(rhs < lhs);
2114 friend bool operator>=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept
2116 return !(lhs < rhs);
2119 friend datum_impl operator+(datum_impl
const &lhs, datum_impl
const &rhs)
2121 if (lhs.is_float() || rhs.is_float()) {
2122 ttlet lhs_ =
static_cast<double>(lhs);
2123 ttlet rhs_ =
static_cast<double>(rhs);
2124 return datum_impl{lhs_ + rhs_};
2126 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2127 ttlet lhs_ =
static_cast<decimal
>(lhs);
2128 ttlet rhs_ =
static_cast<decimal
>(rhs);
2129 return datum_impl{lhs_ + rhs_};
2131 }
else if (lhs.is_integer() || rhs.is_integer()) {
2132 ttlet lhs_ =
static_cast<long long int>(lhs);
2133 ttlet rhs_ =
static_cast<long long int>(rhs);
2134 return datum_impl{lhs_ + rhs_};
2136 }
else if (lhs.is_string() && rhs.is_string()) {
2139 return datum_impl{
std::move(lhs_ + rhs_)};
2141 }
else if (lhs.is_vector() && rhs.is_vector()) {
2142 auto lhs_ =
static_cast<datum_impl::vector
>(lhs);
2143 ttlet &rhs_ = *(rhs.get_pointer<datum_impl::vector>());
2147 }
else if (lhs.is_map() && rhs.is_map()) {
2148 ttlet &lhs_ = *(lhs.get_pointer<datum_impl::map>());
2149 auto rhs_ =
static_cast<datum_impl::map
>(rhs);
2150 for (ttlet &item : lhs_) {
2151 rhs_.try_emplace(item.first, item.second);
2156 throw operation_error(
2157 "Can't add '+' value {} of type {} to value {} of type {}",
2165 friend datum_impl operator-(datum_impl
const &lhs, datum_impl
const &rhs)
2167 if (lhs.is_float() || rhs.is_float()) {
2168 ttlet lhs_ =
static_cast<double>(lhs);
2169 ttlet rhs_ =
static_cast<double>(rhs);
2170 return datum_impl{lhs_ - rhs_};
2172 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2173 ttlet lhs_ =
static_cast<decimal
>(lhs);
2174 ttlet rhs_ =
static_cast<decimal
>(rhs);
2175 return datum_impl{lhs_ - rhs_};
2177 }
else if (lhs.is_integer() || rhs.is_integer()) {
2178 ttlet lhs_ =
static_cast<long long int>(lhs);
2179 ttlet rhs_ =
static_cast<long long int>(rhs);
2180 return datum_impl{lhs_ - rhs_};
2183 throw operation_error(
2184 "Can't subtract '-' value {} of type {} from value {} of type {}",
2192 friend datum_impl operator*(datum_impl
const &lhs, datum_impl
const &rhs)
2194 if (lhs.is_float() || rhs.is_float()) {
2195 ttlet lhs_ =
static_cast<double>(lhs);
2196 ttlet rhs_ =
static_cast<double>(rhs);
2197 return datum_impl{lhs_ * rhs_};
2199 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2200 ttlet lhs_ =
static_cast<decimal
>(lhs);
2201 ttlet rhs_ =
static_cast<decimal
>(rhs);
2202 return datum_impl{lhs_ * rhs_};
2204 }
else if (lhs.is_integer() || rhs.is_integer()) {
2205 ttlet lhs_ =
static_cast<long long int>(lhs);
2206 ttlet rhs_ =
static_cast<long long int>(rhs);
2207 return datum_impl{lhs_ * rhs_};
2210 throw operation_error(
2211 "Can't multiply '*' value {} of type {} with value {} of type {}",
2219 friend datum_impl operator/(datum_impl
const &lhs, datum_impl
const &rhs)
2221 if (lhs.is_float() || rhs.is_float()) {
2222 ttlet lhs_ =
static_cast<double>(lhs);
2223 ttlet rhs_ =
static_cast<double>(rhs);
2224 return datum_impl{lhs_ / rhs_};
2226 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2227 ttlet lhs_ =
static_cast<decimal
>(lhs);
2228 ttlet rhs_ =
static_cast<decimal
>(rhs);
2229 return datum_impl{lhs_ / rhs_};
2231 }
else if (lhs.is_integer() || rhs.is_integer()) {
2232 ttlet lhs_ =
static_cast<long long int>(lhs);
2233 ttlet rhs_ =
static_cast<long long int>(rhs);
2234 return datum_impl{lhs_ / rhs_};
2236 }
else if (lhs.is_url() && (rhs.is_url() || rhs.is_string())) {
2237 ttlet lhs_ =
static_cast<URL
>(lhs);
2238 ttlet rhs_ =
static_cast<URL
>(rhs);
2239 return datum_impl{lhs_ / rhs_};
2242 throw operation_error(
2243 "Can't divide '/' value {} of type {} by value {} of type {}",
2251 friend datum_impl operator%(datum_impl
const &lhs, datum_impl
const &rhs)
2253 if (lhs.is_float() || rhs.is_float()) {
2254 ttlet lhs_ =
static_cast<double>(lhs);
2255 ttlet rhs_ =
static_cast<double>(rhs);
2256 return datum_impl{
fmod(lhs_, rhs_)};
2258 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2259 ttlet lhs_ =
static_cast<decimal
>(lhs);
2260 ttlet rhs_ =
static_cast<decimal
>(rhs);
2261 return datum_impl{lhs_ % rhs_};
2263 }
else if (lhs.is_integer() || rhs.is_integer()) {
2264 ttlet lhs_ =
static_cast<long long int>(lhs);
2265 ttlet rhs_ =
static_cast<long long int>(rhs);
2266 return datum_impl{lhs_ % rhs_};
2269 throw operation_error(
2270 "Can't take modulo '%' value {} of type {} by value {} of type {}",
2278 friend datum_impl operator<<(datum_impl
const &lhs, datum_impl
const &rhs)
2280 if (lhs.is_integer() && rhs.is_integer()) {
2281 ttlet lhs_ =
static_cast<long long>(lhs);
2282 ttlet rhs_ =
static_cast<long long>(rhs);
2289 throw operation_error(
"lhs value {} of left shift must not be negative", lhs);
2293 return datum_impl{0};
2295 return datum_impl{lhs_ << rhs_};
2299 throw operation_error(
2300 "Can't arithmetic shift-left '<<' value {} of type {} with value {} of type {}",
2308 friend datum_impl operator>>(datum_impl
const &lhs, datum_impl
const &rhs)
2310 if (lhs.is_integer() && rhs.is_integer()) {
2311 ttlet lhs_ =
static_cast<long long>(lhs);
2312 ttlet rhs_ =
static_cast<long long>(rhs);
2319 return lhs_ < 0 ? datum_impl{-1} : datum_impl{0};
2321 return datum_impl{lhs_ >> rhs_};
2325 throw operation_error(
2326 "Can't arithmetic shift-right '>>' value {} of type {} with value {} of type {}",
2334 friend datum_impl operator&(datum_impl
const &lhs, datum_impl
const &rhs)
2336 if (lhs.is_integer() && rhs.is_integer()) {
2337 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2338 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2339 return datum_impl{lhs_ & rhs_};
2342 throw operation_error(
2343 "Can't AND '&' value {} of type {} with value {} of type {}",
2351 friend datum_impl operator|(datum_impl
const &lhs, datum_impl
const &rhs)
2353 if (lhs.is_integer() && rhs.is_integer()) {
2354 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2355 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2356 return datum_impl{lhs_ | rhs_};
2359 throw operation_error(
2360 "Can't OR '|' value {} of type {} with value {} of type {}",
2368 friend datum_impl operator^(datum_impl
const &lhs, datum_impl
const &rhs)
2370 if (lhs.is_integer() && rhs.is_integer()) {
2371 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2372 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2373 return datum_impl{lhs_ ^ rhs_};
2376 throw operation_error(
2377 "Can't XOR '^' value {} of type {} with value {} of type {}",
2392 return os << static_cast<std::string>(d);
2395 friend void swap(datum_impl &lhs, datum_impl &rhs)
noexcept
2400 friend datum_impl pow(datum_impl
const &lhs, datum_impl
const &rhs)
2402 if (lhs.is_numeric() || rhs.is_numeric()) {
2403 ttlet lhs_ =
static_cast<double>(lhs);
2404 ttlet rhs_ =
static_cast<double>(rhs);
2405 return datum_impl{
std::pow(lhs_, rhs_)};
2408 throw operation_error(
2409 "Can't raise to a power '**' value {} of type {} with value {} of type {}",
2428 if (lhs.is_map() && rhs.is_map()) {
2432 for (
auto rhs_i = rhs.map_begin(); rhs_i != rhs.map_end(); rhs_i++) {
2433 auto result_i = result_map->
find(rhs_i->first);
2434 if (result_i == result_map->end()) {
2435 result_map->insert(*rhs_i);
2437 result_i->second =
deep_merge(result_i->second, rhs_i->second);
2441 }
else if (lhs.is_vector() && rhs.is_vector()) {
2445 for (
auto rhs_i = rhs.vector_begin(); rhs_i != rhs.vector_end(); rhs_i++) {
2456 template<
typename Alternative>
2457 friend bool holds_alternative(
datum_impl const &rhs)
noexcept
2459 if constexpr (std::is_same_v<Alternative, std::string>) {
2460 return rhs.is_string();