113 static constexpr uint64_t make_string(std::string_view str) {
114 ttlet len = str.size();
121 for (uint64_t i = 0; i < len; i++) {
125 return (string_mask + (len << 48)) | x;
134 static uint64_t make_pointer(uint64_t mask,
void *ptr) {
135 return mask | (
reinterpret_cast<uint64_t
>(ptr) & pointer_mask);
143 static constexpr uint64_t id_to_mask(uint64_t
id) {
155 static constexpr uint16_t make_id(uint16_t
id) {
156 return ((
id & 0x10) << 11) | (
id & 0xf) | 0x7ff0;
160 static constexpr int64_t minimum_int = 0xfffc'0000'0000'0000LL;
162 static constexpr int64_t maximum_int = 0x0003'ffff'ffff'ffffLL;
164 static constexpr int64_t minimum_mantissa = 0xffff'ff80'0000'0000LL;
165 static constexpr int64_t maximum_mantissa = 0x0000'007f'ffff'ffffLL;
167 static constexpr uint16_t exponent_mask = 0b0111'1111'1111'0000;
168 static constexpr uint64_t pointer_mask = 0x0000'ffff'ffff'ffff;
170 static constexpr uint64_t small_undefined = 0;
171 static constexpr uint64_t small_null = 1;
172 static constexpr uint64_t small_true = 2;
173 static constexpr uint64_t small_false = 3;
174 static constexpr uint64_t small_break = 4;
175 static constexpr uint64_t small_continue = 5;
177 static constexpr uint16_t phy_small_id = make_id(0b00001);
178 static constexpr uint16_t phy_decimal_id = make_id(0b00010);
179 static constexpr uint16_t phy_ymd_id = make_id(0b00011);
180 static constexpr uint16_t phy_reserved_id0 = make_id(0b00100);
181 static constexpr uint16_t phy_reserved_id1 = make_id(0b00101);
182 static constexpr uint16_t phy_reserved_id2 = make_id(0b00110);
183 static constexpr uint16_t phy_reserved_id3 = make_id(0b00111);
184 static constexpr uint16_t phy_integer_id0 = make_id(0b01000);
185 static constexpr uint16_t phy_integer_id1 = make_id(0b01001);
186 static constexpr uint16_t phy_integer_id2 = make_id(0b01010);
187 static constexpr uint16_t phy_integer_id3 = make_id(0b01011);
188 static constexpr uint16_t phy_integer_id4 = make_id(0b01100);
189 static constexpr uint16_t phy_integer_id5 = make_id(0b01101);
190 static constexpr uint16_t phy_integer_id6 = make_id(0b01110);
191 static constexpr uint16_t phy_integer_id7 = make_id(0b01111);
193 static constexpr uint16_t phy_string_id0 = make_id(0b10001);
194 static constexpr uint16_t phy_string_id1 = make_id(0b10010);
195 static constexpr uint16_t phy_string_id2 = make_id(0b10011);
196 static constexpr uint16_t phy_string_id3 = make_id(0b10100);
197 static constexpr uint16_t phy_string_id4 = make_id(0b10101);
198 static constexpr uint16_t phy_string_id5 = make_id(0b10110);
199 static constexpr uint16_t phy_string_id6 = make_id(0b10111);
200 static constexpr uint16_t phy_string_ptr_id = make_id(0b11000);
201 static constexpr uint16_t phy_url_ptr_id = make_id(0b11001);
202 static constexpr uint16_t phy_integer_ptr_id = make_id(0b11010);
203 static constexpr uint16_t phy_vector_ptr_id = make_id(0b11011);
204 static constexpr uint16_t phy_map_ptr_id = make_id(0b11100);
205 static constexpr uint16_t phy_decimal_ptr_id = make_id(0b11101);
206 static constexpr uint16_t phy_reserved_ptr_id0 = make_id(0b11110);
207 static constexpr uint16_t phy_reserved_ptr_id1 = make_id(0b11111);
209 static constexpr uint64_t small_mask = id_to_mask(phy_small_id);
210 static constexpr uint64_t undefined_mask = small_mask | small_undefined;
211 static constexpr uint64_t null_mask = small_mask | small_null;
212 static constexpr uint64_t true_mask = small_mask | small_true;
213 static constexpr uint64_t false_mask = small_mask | small_false;
214 static constexpr uint64_t break_mask = small_mask | small_break;
215 static constexpr uint64_t continue_mask = small_mask | small_continue;
216 static constexpr uint64_t string_mask = id_to_mask(phy_string_id0);
217 static constexpr uint64_t character_mask = id_to_mask(phy_string_id1);
218 static constexpr uint64_t integer_mask = id_to_mask(phy_integer_id0);
219 static constexpr uint64_t decimal_mask = id_to_mask(phy_decimal_id);
220 static constexpr uint64_t ymd_mask = id_to_mask(phy_ymd_id);
221 static constexpr uint64_t string_ptr_mask = id_to_mask(phy_string_ptr_id);
222 static constexpr uint64_t url_ptr_mask = id_to_mask(phy_url_ptr_id);
223 static constexpr uint64_t integer_ptr_mask = id_to_mask(phy_integer_ptr_id);
224 static constexpr uint64_t vector_ptr_mask = id_to_mask(phy_vector_ptr_id);
225 static constexpr uint64_t map_ptr_mask = id_to_mask(phy_map_ptr_id);
226 static constexpr uint64_t decimal_ptr_mask = id_to_mask(phy_decimal_ptr_id);
241 tt_force_inline uint16_t type_id()
const noexcept {
244 return static_cast<uint16_t
>(data >> 48);
247 tt_force_inline
bool is_phy_float()
const noexcept {
248 ttlet
id = type_id();
249 return (
id & 0x7ff0) != 0x7ff0 || (
id & 0x000f) == 0;
252 tt_force_inline
bool is_phy_integer()
const noexcept {
253 return (type_id() & 0xfff8) == 0x7ff8;
256 tt_force_inline
bool is_phy_string()
const noexcept {
257 ttlet
id = type_id();
258 return (
id & 0xfff8) == 0xfff0 && (
id & 0x0007) > 0;
261 tt_force_inline
bool is_phy_decimal()
const noexcept {
262 return type_id() == phy_decimal_id;
265 tt_force_inline
bool is_phy_ymd()
const noexcept {
266 return type_id() == phy_ymd_id;
269 tt_force_inline
bool is_phy_small()
const noexcept {
270 return type_id() == phy_small_id;
273 tt_force_inline
bool is_phy_pointer()
const noexcept {
274 return HasLargeObjects && (type_id() & 0xfff8) == 0xfff8;
277 tt_force_inline
bool is_phy_string_ptr()
const noexcept {
278 return HasLargeObjects && type_id() == phy_string_ptr_id;
281 tt_force_inline
bool is_phy_url_ptr()
const noexcept {
282 return HasLargeObjects && type_id() == phy_url_ptr_id;
285 tt_force_inline
bool is_phy_integer_ptr()
const noexcept {
286 return HasLargeObjects && type_id() == phy_integer_ptr_id;
289 tt_force_inline
bool is_phy_vector_ptr()
const noexcept {
290 return HasLargeObjects && type_id() == phy_vector_ptr_id;
293 tt_force_inline
bool is_phy_map_ptr()
const noexcept {
294 return HasLargeObjects && type_id() == phy_map_ptr_id;
297 tt_force_inline
bool is_phy_decimal_ptr()
const noexcept {
298 return HasLargeObjects && type_id() == phy_decimal_ptr_id;
303 tt_force_inline uint64_t get_unsigned_integer()
const noexcept {
304 return (u64 << 16) >> 16;
309 tt_force_inline int64_t get_signed_integer()
const noexcept {
310 return static_cast<int64_t
>(u64 << 16) >> 16;
318 tt_force_inline O *get_pointer()
const {
319 return std::launder(
reinterpret_cast<O *
>(get_signed_integer()));
325 void delete_pointer()
noexcept {
326 if constexpr (HasLargeObjects) {
328 case phy_integer_ptr_id:
delete get_pointer<int64_t>();
break;
329 case phy_string_ptr_id:
delete get_pointer<std::string>();
break;
330 case phy_url_ptr_id:
delete get_pointer<URL>();
break;
331 case phy_vector_ptr_id:
delete get_pointer<datum_impl::vector>();
break;
332 case phy_map_ptr_id:
delete get_pointer<datum_impl::map>();
break;
333 case phy_decimal_ptr_id:
delete get_pointer<decimal>();
break;
334 default: tt_no_default;
344 void copy_pointer(
datum_impl const &other)
noexcept {
345 if constexpr (HasLargeObjects) {
346 switch (other.type_id()) {
347 case phy_integer_ptr_id: {
348 auto *
const p =
new int64_t(*other.get_pointer<int64_t>());
349 u64 = make_pointer(integer_ptr_mask, p);
352 case phy_string_ptr_id: {
354 u64 = make_pointer(string_ptr_mask, p);
357 case phy_url_ptr_id: {
358 auto *
const p =
new URL(*other.get_pointer<
URL>());
359 u64 = make_pointer(url_ptr_mask, p);
362 case phy_vector_ptr_id: {
364 u64 = make_pointer(vector_ptr_mask, p);
367 case phy_map_ptr_id: {
369 u64 = make_pointer(map_ptr_mask, p);
372 case phy_decimal_ptr_id: {
374 u64 = make_pointer(decimal_ptr_mask, p);
392 datum_impl() noexcept : u64(undefined_mask) {}
395 if (tt_unlikely(is_phy_pointer())) {
400 datum_impl(datum_impl
const &other)
noexcept {
401 if (tt_unlikely(other.is_phy_pointer())) {
409 datum_impl &operator=(datum_impl
const &other)
noexcept {
410 if (
this != &other) {
411 if (tt_unlikely(is_phy_pointer())) {
414 if (tt_unlikely(other.is_phy_pointer())) {
424 datum_impl(datum_impl &&other) noexcept : u64(undefined_mask) {
427 other.u64 = undefined_mask;
430 datum_impl &operator=(datum_impl &&other)
noexcept {
431 if (
this != &other) {
435 other.u64 = undefined_mask;
439 datum_impl(datum_impl::undefined) noexcept : u64(undefined_mask) {}
440 datum_impl(datum_impl::null) noexcept : u64(null_mask) {}
441 datum_impl(datum_impl::_break) noexcept : u64(break_mask) {}
442 datum_impl(datum_impl::_continue) noexcept : u64(continue_mask) {}
444 datum_impl(
double value) noexcept : f64(value) {
445 if (value != value) {
446 u64 = undefined_mask;
449 datum_impl(
float value) noexcept : datum_impl(
static_cast<double>(value)) {}
451 datum_impl(decimal value)
noexcept {
452 long long m = value.mantissa();
454 if (tt_unlikely(m < minimum_mantissa || m > maximum_mantissa)) {
455 if constexpr (HasLargeObjects) {
456 auto*
const p =
new decimal(value);
457 u64 = make_pointer(decimal_ptr_mask, p);
459 TTAURI_THROW_MATH_ERROR(
"Constructing decimal {} to datum", value);
462 int e = value.exponent();
466 static_cast<uint8_t
>(e) |
467 ((
static_cast<uint64_t
>(m) << 24) >> 16);
471 datum_impl(date::year_month_day
const &ymd) noexcept :
474 (
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
475 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
476 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))
477 ) & 0x0000ffff'ffffffff)
480 datum_impl(
unsigned long long value) noexcept : u64(integer_mask | value) {
481 if (tt_unlikely(value > maximum_int)) {
482 if constexpr (HasLargeObjects) {
483 auto *
const p =
new uint64_t(value);
484 u64 = make_pointer(integer_ptr_mask, p);
486 TTAURI_THROW_MATH_ERROR(
"Constructing datum from integer {}, larger than {}", value, maximum_int);
490 datum_impl(
unsigned long value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
491 datum_impl(
unsigned int value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
492 datum_impl(
unsigned short value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
493 datum_impl(
unsigned char value) noexcept : datum_impl(
static_cast<unsigned long long>(value)) {}
495 datum_impl(
signed long long value) noexcept :
496 u64(integer_mask | (
static_cast<uint64_t
>(value) & 0x0007ffff'ffffffff))
498 if (tt_unlikely(value < minimum_int || value > maximum_int)) {
499 if constexpr (HasLargeObjects) {
500 auto *
const p =
new int64_t(value);
501 u64 = make_pointer(integer_ptr_mask, p);
503 TTAURI_THROW_MATH_ERROR(
"Constructing integer {} to datum, outside {} and {}", value, minimum_int, maximum_int);
507 datum_impl(
signed long value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
508 datum_impl(
signed int value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
509 datum_impl(
signed short value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
510 datum_impl(
signed char value) noexcept : datum_impl(
static_cast<signed long long>(value)) {}
512 datum_impl(
bool value) noexcept : u64(value ? true_mask : false_mask) {}
513 datum_impl(
char value) noexcept : u64(character_mask | value) {}
515 datum_impl(std::string_view value) noexcept : u64(make_string(value)) {
516 if (value.size() > 6) {
517 if constexpr (HasLargeObjects) {
519 u64 = make_pointer(string_ptr_mask, p);
521 TTAURI_THROW_MATH_ERROR(
"Constructing string {} to datum, larger than 6 characters", value);
526 datum_impl(
std::string const &value) noexcept : datum_impl(std::string_view(value)) {}
527 datum_impl(
char const *value) noexcept : datum_impl(std::string_view(value)) {}
529 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
530 datum_impl(URL
const &value)
noexcept {
531 auto *
const p =
new URL(value);
532 u64 = make_pointer(url_ptr_mask, p);
535 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
536 datum_impl(URL &&value)
noexcept {
537 auto *
const p =
new URL(
std::move(value));
538 u64 = make_pointer(url_ptr_mask, p);
541 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
542 datum_impl(datum_impl::vector
const &value)
noexcept {
543 auto *
const p =
new datum_impl::vector(value);
544 u64 = make_pointer(vector_ptr_mask, p);
547 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
548 datum_impl(datum_impl::vector &&value)
noexcept {
549 auto *
const p =
new datum_impl::vector(
std::move(value));
550 u64 = make_pointer(vector_ptr_mask, p);
553 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
554 datum_impl(datum_impl::map
const &value)
noexcept {
555 auto *
const p =
new datum_impl::map(value);
556 u64 = make_pointer(map_ptr_mask, p);
559 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
560 datum_impl(datum_impl::map &&value)
noexcept {
561 auto *
const p =
new datum_impl::map(
std::move(value));
562 u64 = make_pointer(map_ptr_mask, p);
565 datum_impl &operator=(datum_impl::undefined rhs)
noexcept {
566 if (tt_unlikely(is_phy_pointer())) {
569 u64 = undefined_mask;
573 datum_impl &operator=(datum_impl::null rhs)
noexcept {
574 if (tt_unlikely(is_phy_pointer())) {
581 datum_impl &operator=(datum_impl::_break rhs)
noexcept {
582 if (tt_unlikely(is_phy_pointer())) {
589 datum_impl &operator=(datum_impl::_continue rhs)
noexcept {
590 if (tt_unlikely(is_phy_pointer())) {
597 datum_impl &operator=(
double rhs)
noexcept {
598 if (tt_unlikely(is_phy_pointer())) {
605 u64 = undefined_mask;
609 datum_impl& operator=(
float rhs)
noexcept {
return *
this =
static_cast<double>(rhs); }
612 datum_impl& operator=(decimal rhs)
noexcept {
613 if (tt_unlikely(is_phy_pointer())) {
617 long long m = rhs.mantissa();
618 if (tt_unlikely(m < minimum_mantissa || m > maximum_mantissa)) {
619 if constexpr (HasLargeObjects) {
620 auto*
const p =
new decimal(rhs);
621 u64 = make_pointer(decimal_ptr_mask, p);
623 TTAURI_THROW_MATH_ERROR(
"Constructing decimal {} to datum", rhs);
626 int e = rhs.exponent();
630 static_cast<uint8_t
>(e) |
631 ((
static_cast<uint64_t
>(m) << 24) >> 16);
636 datum_impl &operator=(date::year_month_day
const & ymd)
noexcept {
637 if (tt_unlikely(is_phy_pointer())) {
642 (
static_cast<uint64_t
>(
static_cast<int>(ymd.year())) << 9) |
643 (
static_cast<uint64_t
>(
static_cast<unsigned>(ymd.month())) << 5) |
644 static_cast<uint64_t
>(
static_cast<unsigned>(ymd.day()))
645 ) & 0x0000ffff'ffffffff);
649 datum_impl &operator=(
unsigned long long rhs)
noexcept {
650 if (tt_unlikely(is_phy_pointer())) {
654 u64 = integer_mask |
static_cast<uint64_t
>(rhs);
655 if (tt_unlikely(rhs > maximum_int)) {
656 if constexpr (HasLargeObjects) {
657 auto *
const p =
new uint64_t(rhs);
658 u64 = make_pointer(integer_ptr_mask, p);
660 TTAURI_THROW_MATH_ERROR(
"Assigning integer {} to datum, larger than {}", rhs, maximum_int);
665 datum_impl& operator=(
unsigned long rhs)
noexcept {
return *
this =
static_cast<unsigned long long>(rhs); }
666 datum_impl& operator=(
unsigned int rhs)
noexcept {
return *
this =
static_cast<unsigned long long>(rhs); }
667 datum_impl& operator=(
unsigned short rhs)
noexcept {
return *
this =
static_cast<unsigned long long>(rhs); }
668 datum_impl& operator=(
unsigned char rhs)
noexcept {
return *
this =
static_cast<unsigned long long>(rhs); }
670 datum_impl &operator=(
signed long long rhs)
noexcept {
671 if (tt_unlikely(is_phy_pointer())) {
675 u64 = integer_mask | (
static_cast<uint64_t
>(rhs) & 0x0007ffff'ffffffff);
676 if (tt_unlikely(rhs < minimum_int || rhs > maximum_int)) {
677 if constexpr (HasLargeObjects) {
678 auto *
const p =
new int64_t(rhs);
679 u64 = make_pointer(integer_ptr_mask, p);
681 TTAURI_THROW_MATH_ERROR(
"Assigning integer {} to datum, outside {} and {}", rhs, minimum_int, maximum_int);
687 datum_impl& operator=(
signed long rhs)
noexcept {
return *
this =
static_cast<signed long long>(rhs); }
688 datum_impl& operator=(
signed int rhs)
noexcept {
return *
this =
static_cast<signed long long>(rhs); }
689 datum_impl& operator=(
signed short rhs)
noexcept {
return *
this =
static_cast<signed long long>(rhs); }
690 datum_impl& operator=(
signed char rhs)
noexcept {
return *
this =
static_cast<signed long long>(rhs); }
692 datum_impl &operator=(
bool rhs)
noexcept {
693 if (tt_unlikely(is_phy_pointer())) {
696 u64 = rhs ? true_mask : false_mask;
700 datum_impl &operator=(
char rhs)
noexcept {
701 if (tt_unlikely(is_phy_pointer())) {
704 u64 = character_mask |
static_cast<uint64_t
>(rhs);
708 datum_impl &operator=(std::string_view rhs) {
709 if (tt_unlikely(is_phy_pointer())) {
713 u64 = make_string(rhs);
714 if (rhs.size() > 6) {
715 if constexpr (HasLargeObjects) {
717 u64 = make_pointer(string_ptr_mask, p);
719 TTAURI_THROW_MATH_ERROR(
"Assigning string {} to datum, larger than 6 characters", rhs);
726 *
this = std::string_view{rhs};
730 datum_impl &operator=(
char const *rhs) {
731 *
this = std::string_view{rhs};
735 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
736 datum_impl &operator=(URL
const &rhs)
noexcept {
737 if (tt_unlikely(is_phy_pointer())) {
741 auto *
const p =
new URL(rhs);
742 u64 = make_pointer(url_ptr_mask, p);
746 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
747 datum_impl &operator=(URL &&rhs)
noexcept {
748 if (tt_unlikely(is_phy_pointer())) {
752 auto *
const p =
new URL(
std::move(rhs));
753 u64 = make_pointer(url_ptr_mask, p);
757 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
758 datum_impl &operator=(datum_impl::vector
const &rhs) {
759 if (tt_unlikely(is_phy_pointer())) {
763 auto *
const p =
new datum_impl::vector(rhs);
764 u64 = make_pointer(vector_ptr_mask, p);
769 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
770 datum_impl &operator=(datum_impl::vector &&rhs) {
771 if (tt_unlikely(is_phy_pointer())) {
775 auto *
const p =
new datum_impl::vector(
std::move(rhs));
776 u64 = make_pointer(vector_ptr_mask, p);
782 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
783 datum_impl &operator=(datum_impl::map
const &rhs) {
784 if (tt_unlikely(is_phy_pointer())) {
788 auto *
const p =
new datum_impl::map(rhs);
789 u64 = make_pointer(map_ptr_mask, p);
794 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
795 datum_impl &operator=(datum_impl::map &&rhs) {
796 if (tt_unlikely(is_phy_pointer())) {
800 auto *
const p =
new datum_impl::map(
std::move(rhs));
801 u64 = make_pointer(map_ptr_mask, p);
806 explicit operator double()
const {
807 if (is_phy_float()) {
809 }
else if (is_decimal()) {
810 return static_cast<double>(
static_cast<decimal
>(*this));
811 }
else if (is_phy_integer()) {
812 return static_cast<double>(get_signed_integer());
813 }
else if (is_phy_integer_ptr()) {
814 return static_cast<double>(*get_pointer<int64_t>());
816 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a double", this->repr(), this->type_name());
820 explicit operator float()
const {
821 return static_cast<float>(
static_cast<double>(*this));
824 explicit operator decimal()
const {
825 if (is_phy_decimal()) {
826 uint64_t v = get_unsigned_integer();
827 int e =
static_cast<int8_t
>(v);
828 long long m =
static_cast<int64_t
>(v << 16) >> 24;
829 return decimal{e, m};
830 }
else if (is_phy_decimal_ptr()) {
831 return *get_pointer<decimal>();
832 }
else if (is_phy_integer() || is_phy_integer_ptr()) {
833 return decimal{
static_cast<signed long long>(*this)};
834 }
else if (is_phy_float()) {
835 return decimal{
static_cast<double>(*this)};
837 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a decimal", this->repr(), this->type_name());
841 explicit operator date::year_month_day()
const {
843 ttlet u = get_unsigned_integer();
844 ttlet i = get_signed_integer();
845 ttlet day =
static_cast<unsigned>(u & 0x1f);
846 ttlet month =
static_cast<unsigned>((u >> 5) & 0xf);
847 ttlet year =
static_cast<signed>(i >> 9);
850 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
853 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
855 return date::year_month_day{date::year{year}, date::month{month}, date::day{day}};
857 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a year-month-day", this->repr(), this->type_name());
861 explicit operator signed long long ()
const {
862 if (is_phy_integer()) {
863 return get_signed_integer();
864 }
else if (is_phy_integer_ptr()) {
865 return *get_pointer<signed long long>();
866 }
else if (is_phy_float()) {
867 return static_cast<signed long long>(f64);
868 }
else if (is_phy_small()) {
869 switch (get_unsigned_integer()) {
870 case small_true:
return 1;
871 case small_false:
return 0;
874 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a signed long long", this->repr(), this->type_name());
877 explicit operator signed long ()
const {
878 ttlet v =
static_cast<signed long long>(*this);
880 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a signed long", this->repr(), this->type_name());
882 return static_cast<signed long>(v);
885 explicit operator signed int ()
const {
886 ttlet v =
static_cast<signed long long>(*this);
888 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a signed int", this->repr(), this->type_name());
890 return static_cast<signed int>(v);
893 explicit operator signed short ()
const {
894 ttlet v =
static_cast<signed long long>(*this);
896 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a signed short", this->repr(), this->type_name());
898 return static_cast<signed short>(v);
901 explicit operator signed char ()
const {
902 ttlet v =
static_cast<int64_t
>(*this);
904 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a signed char", this->repr(), this->type_name());
906 return static_cast<signed char>(v);
909 explicit operator unsigned long long ()
const {
910 ttlet v =
static_cast<signed long long>(*this);
911 return static_cast<unsigned long long>(v);
914 explicit operator unsigned long ()
const {
915 ttlet v =
static_cast<unsigned long long>(*this);
917 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a unsigned long", this->repr(), this->type_name());
919 return static_cast<unsigned long>(v);
922 explicit operator unsigned int ()
const {
923 ttlet v =
static_cast<unsigned long long>(*this);
925 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a unsigned int", this->repr(), this->type_name());
927 return static_cast<unsigned int>(v);
930 explicit operator unsigned short ()
const {
931 ttlet v =
static_cast<unsigned long long>(*this);
933 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a unsigned short", this->repr(), this->type_name());
935 return static_cast<unsigned short>(v);
938 explicit operator unsigned char ()
const {
939 ttlet v =
static_cast<unsigned long long>(*this);
941 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a unsigned char", this->repr(), this->type_name());
943 return static_cast<unsigned char>(v);
946 explicit operator bool() const noexcept {
948 case phy_small_id:
return get_unsigned_integer() == small_true;
949 case phy_integer_id0:
950 case phy_integer_id1:
951 case phy_integer_id2:
952 case phy_integer_id3:
953 case phy_integer_id4:
954 case phy_integer_id5:
955 case phy_integer_id6:
956 case phy_integer_id7:
return static_cast<int64_t
>(*this) != 0;
957 case phy_decimal_id:
return static_cast<decimal
>(*this) != 0;
958 case phy_ymd_id:
return true;
959 case phy_integer_ptr_id:
return *get_pointer<int64_t>() != 0;
967 case phy_string_ptr_id:
return this->size() > 0;
968 case phy_url_ptr_id:
return true;
969 case phy_vector_ptr_id:
return this->size() > 0;
970 case phy_map_ptr_id:
return this->size() > 0;
971 case phy_decimal_ptr_id:
return static_cast<decimal
>(*this) != 0;
973 if (tt_likely(is_phy_float())) {
974 return static_cast<double>(*this) != 0.0;
981 explicit operator char()
const {
982 if (is_phy_string() && size() == 1) {
984 }
else if (is_phy_string_ptr() && size() == 1) {
985 return get_pointer<std::string>()->at(0);
987 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a char", this->repr(), this->type_name());
994 switch (get_unsigned_integer()) {
995 case small_undefined:
return "undefined";
996 case small_null:
return "null";
997 case small_true:
return "true";
998 case small_false:
return "false";
999 case small_break:
return "break";
1000 case small_continue:
return "continue";
1001 default: tt_no_default;
1004 case phy_integer_id0:
1005 case phy_integer_id1:
1006 case phy_integer_id2:
1007 case phy_integer_id3:
1008 case phy_integer_id4:
1009 case phy_integer_id5:
1010 case phy_integer_id6:
1011 case phy_integer_id7:
return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1012 case phy_decimal_id:
return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1013 case phy_ymd_id:
return fmt::format(
"{}",
static_cast<date::year_month_day
>(*
this));
1014 case phy_integer_ptr_id:
1015 if constexpr (HasLargeObjects) {
1016 return fmt::format(
"{}",
static_cast<int64_t
>(*
this));
1021 case phy_string_id0:
1022 case phy_string_id1:
1023 case phy_string_id2:
1024 case phy_string_id3:
1025 case phy_string_id4:
1026 case phy_string_id5:
1027 case phy_string_id6: {
1028 ttlet length = size();
1030 for (
int i = 0; i < length; i++) {
1031 buffer[i] = (u64 >> ((length - i - 1) * 8)) & 0xff;
1036 case phy_string_ptr_id:
1037 if constexpr (HasLargeObjects) {
1038 return *get_pointer<std::string>();
1043 case phy_url_ptr_id:
1044 if constexpr (HasLargeObjects) {
1045 return get_pointer<URL>()->string();
1050 case phy_decimal_ptr_id:
1051 if constexpr (HasLargeObjects) {
1052 return fmt::format(
"{}",
static_cast<decimal
>(*
this));
1057 case phy_vector_ptr_id:
1058 if constexpr (HasLargeObjects) {
1061 for (
auto i = vector_begin(); i != vector_end(); i++) {
1073 case phy_map_ptr_id:
1074 if constexpr (HasLargeObjects) {
1079 return a.first < b.first;
1084 for (
auto &
item: items) {
1088 r +=
item.first.repr();
1090 r +=
item.second.repr();
1099 if (is_phy_float()) {
1100 auto str = fmt::format(
"{:g}",
static_cast<double>(*
this));
1101 if (str.find(
'.') == str.npos) {
1111 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1112 explicit operator URL()
const {
1115 }
else if (is_url()) {
1116 return *get_pointer<URL>();
1118 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a URL", this->repr(), this->type_name());
1122 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1123 explicit operator datum_impl::vector()
const {
1125 return *get_pointer<datum_impl::vector>();
1127 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a Vector", this->repr(), this->type_name());
1131 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1132 explicit operator datum_impl::map()
const {
1134 return *get_pointer<datum_impl::map>();
1136 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Value {} of type {} can not be converted to a Map", this->repr(), this->type_name());
1147 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1149 if (is_undefined()) {
1152 u64 = map_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1156 auto &m = *get_pointer<datum_impl::map>();
1157 auto [i, did_insert] = m.try_emplace(rhs);
1160 }
else if (is_vector() && rhs.is_integer()) {
1161 auto index =
static_cast<int64_t
>(rhs);
1162 auto &v = *get_pointer<datum_impl::vector>();
1165 index = ssize(v) + index;
1168 if (index < 0 || index >= ssize(v)) {
1169 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Index {} out of range to access value in vector of size {}", index, ssize(v));
1174 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1185 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1188 ttlet &m = *get_pointer<datum_impl::map>();
1189 ttlet i = m.find(rhs);
1190 if (i == m.cend()) {
1191 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Could not find key {} in map of size {}", rhs.repr(), ssize(m));
1195 }
else if (is_vector() && rhs.is_integer()) {
1196 auto index =
static_cast<int64_t
>(rhs);
1197 ttlet &v = *get_pointer<datum_impl::vector>();
1200 index = ssize(v) + index;
1203 if (index < 0 || index >= ssize(v)) {
1204 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Index {} out of range to access value in vector of size {}", index, ssize(v));
1209 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot index value of type {} with {} of type {}", type_name(), rhs.repr(), rhs.type_name());
1221 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1224 ttlet &m = *get_pointer<datum_impl::map>();
1225 ttlet i = m.find(rhs);
1226 return i != m.cend();
1228 }
else if (is_vector() && rhs.is_integer()) {
1229 auto index =
static_cast<int64_t
>(rhs);
1230 ttlet &v = *get_pointer<datum_impl::vector>();
1233 index = ssize(v) + index;
1236 return index >= 0 && index < ssize(v);
1248 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1250 if (is_undefined()) {
1253 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1257 auto *v = get_pointer<datum_impl::vector>();
1262 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot append new item onto type {}", type_name());
1266 template<
typename... Args>
1267 void emplace_back(Args &&... args) {
1268 if (is_undefined()) {
1271 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1275 auto *v = get_pointer<datum_impl::vector>();
1276 v->emplace_back(std::forward<Args>(args)...);
1279 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot append new item onto type {}", type_name());
1283 template<
typename Arg>
1284 void push_back(Arg &&arg) {
1285 if (is_undefined()) {
1287 auto *p =
new datum_impl::vector();
1288 u64 = vector_ptr_mask | (
reinterpret_cast<uint64_t
>(p) & pointer_mask);
1292 auto *v = get_pointer<datum_impl::vector>();
1293 v->push_back(std::forward<Arg>(arg));
1296 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot append new item onto type {}", type_name());
1302 auto *v = get_pointer<datum_impl::vector>();
1306 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot pop_back() onto type {}", type_name());
1310 datum_impl year()
const {
1312 return {
static_cast<signed>(
static_cast<date::year_month_day
>(*this).year())};
1314 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot get year() from type {}", type_name());
1318 datum_impl quarter()
const {
1320 auto month =
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month());
1321 return {((month-1) / 3) + 1};
1323 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot get month() from type {}", type_name());
1327 datum_impl month()
const {
1329 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).month())};
1331 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot get month() from type {}", type_name());
1335 datum_impl day()
const {
1337 return {
static_cast<unsigned>(
static_cast<date::year_month_day
>(*this).day())};
1339 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot get day() from type {}", type_name());
1343 datum_impl
const &front()
const {
1345 ttlet *v = get_pointer<datum_impl::vector>();
1349 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot front() onto type {}", type_name());
1353 datum_impl &front() {
1355 auto *v = get_pointer<datum_impl::vector>();
1359 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot front() onto type {}", type_name());
1363 datum_impl
const &back()
const {
1365 ttlet *v = get_pointer<datum_impl::vector>();
1369 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot back() onto type {}", type_name());
1373 datum_impl &back() {
1375 auto *v = get_pointer<datum_impl::vector>();
1379 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Cannot back() onto type {}", type_name());
1385 switch (type_id()) {
1387 switch (get_unsigned_integer()) {
1388 case small_undefined:
return "undefined";
1389 case small_null:
return "null";
1390 case small_true:
return "true";
1391 case small_false:
return "false";
1392 case small_break:
return "break";
1393 case small_continue:
return "continue";
1394 default: tt_no_default;
1396 case phy_integer_id0:
1397 case phy_integer_id1:
1398 case phy_integer_id2:
1399 case phy_integer_id3:
1400 case phy_integer_id4:
1401 case phy_integer_id5:
1402 case phy_integer_id6:
1403 case phy_integer_id7:
1404 case phy_integer_ptr_id:
return static_cast<std::string>(*this);
1405 case phy_decimal_id:
1406 case phy_decimal_ptr_id:
return static_cast<std::string>(*this);
1407 case phy_ymd_id:
return static_cast<std::string>(*this);
1408 case phy_string_id0:
1409 case phy_string_id1:
1410 case phy_string_id2:
1411 case phy_string_id3:
1412 case phy_string_id4:
1413 case phy_string_id5:
1414 case phy_string_id6:
1415 case phy_string_ptr_id:
return fmt::format(
"\"{}\"",
static_cast<std::string>(*
this));
1416 case phy_url_ptr_id:
return fmt::format(
"<URL {}>",
static_cast<std::string>(*
this));
1417 case phy_vector_ptr_id:
return static_cast<std::string>(*this);
1418 case phy_map_ptr_id:
return static_cast<std::string>(*this);
1420 if (tt_likely(is_phy_float())) {
1434 return phy_integer_id0;
1441 if (key.
size() > 0 && is_map()) {
1442 ttlet index = key.
at(0);
1443 auto &next = (*this)[index];
1445 return next.get_by_path(next_key);
1447 }
else if (key.
size() > 0 && is_vector()) {
1449 auto &
next = (*this)[index];
1451 return next.get_by_path(next_key);
1453 }
else if (key.
size() > 0) {
1454 TTAURI_THROW_INVALID_OPERATION_ERROR(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1461 if (key.
size() > 0 && is_map()) {
1462 ttlet index = key.
at(0);
1463 ttlet
next = (*this)[index];
1466 }
else if (key.
size() > 0 && is_vector()) {
1468 ttlet
next = (*this)[index];
1471 }
else if (key.
size() > 0) {
1472 TTAURI_THROW_INVALID_OPERATION_ERROR(
"type {} does not support get() with '{}'", type_name(), key.
at(0));
1478 tt_force_inline
bool is_integer() const noexcept {
return is_phy_integer() || is_phy_integer_ptr(); }
1479 tt_force_inline
bool is_decimal() const noexcept {
return is_phy_decimal() || is_phy_decimal_ptr(); }
1480 tt_force_inline
bool is_ymd() const noexcept {
return is_phy_ymd(); }
1481 tt_force_inline
bool is_float() const noexcept {
return is_phy_float(); }
1482 tt_force_inline
bool is_string() const noexcept {
return is_phy_string() || is_phy_string_ptr(); }
1484 tt_force_inline
bool is_bool() const noexcept {
1485 if (is_phy_small()) {
1486 ttlet tmp = get_unsigned_integer();
1487 return tmp == small_true || tmp == small_false;
1493 tt_force_inline
bool is_null() const noexcept {
1494 return is_phy_small() && get_unsigned_integer() == small_null;
1497 tt_force_inline
bool is_undefined() const noexcept {
1498 return is_phy_small() && get_unsigned_integer() == small_undefined;
1501 tt_force_inline
bool is_break() const noexcept {
1502 return is_phy_small() && get_unsigned_integer() == small_break;
1505 tt_force_inline
bool is_continue() const noexcept {
1506 return is_phy_small() && get_unsigned_integer() == small_continue;
1507 }
bool is_url() const noexcept {
return is_phy_url_ptr(); }
1509 tt_force_inline
bool is_vector() const noexcept {
return is_phy_vector_ptr(); }
1510 tt_force_inline
bool is_map() const noexcept {
return is_phy_map_ptr(); }
1511 tt_force_inline
bool is_numeric() const noexcept {
return is_integer() || is_decimal() || is_float(); }
1513 datum_type_t type() const noexcept {
1514 switch (type_id()) {
1516 switch (get_unsigned_integer()) {
1517 case small_undefined:
return datum_type_t::Undefined;
1518 case small_null:
return datum_type_t::Null;
1519 case small_false:
return datum_type_t::Boolean;
1520 case small_true:
return datum_type_t::Boolean;
1521 case small_break:
return datum_type_t::Break;
1522 case small_continue:
return datum_type_t::Continue;
1523 default: tt_no_default;
1526 case phy_integer_id0:
1527 case phy_integer_id1:
1528 case phy_integer_id2:
1529 case phy_integer_id3:
1530 case phy_integer_id4:
1531 case phy_integer_id5:
1532 case phy_integer_id6:
1533 case phy_integer_id7:
1534 case phy_integer_ptr_id:
return datum_type_t::Integer;
1535 case phy_decimal_id:
1536 case phy_decimal_ptr_id:
return datum_type_t::Decimal;
1537 case phy_ymd_id:
return datum_type_t::YearMonthDay;
1538 case phy_string_id0:
1539 case phy_string_id1:
1540 case phy_string_id2:
1541 case phy_string_id3:
1542 case phy_string_id4:
1543 case phy_string_id5:
1544 case phy_string_id6:
1545 case phy_string_ptr_id:
return datum_type_t::String;
1546 case phy_url_ptr_id:
return datum_type_t::URL;
1547 case phy_vector_ptr_id:
return datum_type_t::Vector;
1548 case phy_map_ptr_id:
return datum_type_t::Map;
1550 if (tt_likely(is_phy_float())) {
1551 return datum_type_t::Float;
1558 char const *type_name() const noexcept{
1559 switch (type_id()) {
1561 switch (get_unsigned_integer()) {
1562 case small_undefined:
return "Undefined";
1563 case small_null:
return "Null";
1564 case small_false:
return "Boolean";
1565 case small_true:
return "Boolean";
1566 case small_break:
return "Break";
1567 case small_continue:
return "Continue";
1568 default: tt_no_default;
1571 case phy_integer_id0:
1572 case phy_integer_id1:
1573 case phy_integer_id2:
1574 case phy_integer_id3:
1575 case phy_integer_id4:
1576 case phy_integer_id5:
1577 case phy_integer_id6:
1578 case phy_integer_id7:
1579 case phy_integer_ptr_id:
return "Integer";
1580 case phy_decimal_id:
1581 case phy_decimal_ptr_id:
return "Decimal";
1582 case phy_ymd_id:
return "YearMonthDay";
1583 case phy_string_id0:
1584 case phy_string_id1:
1585 case phy_string_id2:
1586 case phy_string_id3:
1587 case phy_string_id4:
1588 case phy_string_id5:
1589 case phy_string_id6:
1590 case phy_string_ptr_id:
return "String";
1591 case phy_url_ptr_id:
return "URL";
1592 case phy_vector_ptr_id:
return "Vector";
1593 case phy_map_ptr_id:
return "Map";
1595 if (tt_likely(is_phy_float())) {
1603 size_t size()
const{
1604 switch (type_id()) {
1605 case phy_string_id0:
1606 case phy_string_id1:
1607 case phy_string_id2:
1608 case phy_string_id3:
1609 case phy_string_id4:
1610 case phy_string_id5:
1611 case phy_string_id6:
return ((u64 & 0xffff'0000'0000'0000ULL) - string_mask) >> 48;
1612 case phy_string_ptr_id:
return get_pointer<std::string>()->size();
1613 case phy_vector_ptr_id:
return get_pointer<datum_impl::vector>()->size();
1614 case phy_map_ptr_id:
return get_pointer<datum_impl::map>()->size();
1615 default: TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't get size of value {} of type {}.", this->repr(), this->type_name());
1619 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1620 typename map::const_iterator map_begin() const noexcept {
1621 if (is_phy_map_ptr()) {
1622 return get_pointer<datum_impl::map>()->begin();
1624 TTAURI_THROW_INVALID_OPERATION_ERROR(
"map_begin() expect datum to be a map, but it is a {}.", this->type_name());
1628 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1629 typename map::const_iterator map_end() const noexcept {
1630 if (is_phy_map_ptr()) {
1631 return get_pointer<datum_impl::map>()->end();
1633 TTAURI_THROW_INVALID_OPERATION_ERROR(
"map_end() expect datum to be a map, but it is a {}.", this->type_name());
1637 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1638 typename vector::const_iterator vector_begin() const noexcept {
1639 if (is_phy_vector_ptr()) {
1640 return get_pointer<datum_impl::vector>()->begin();
1642 TTAURI_THROW_INVALID_OPERATION_ERROR(
"vector_begin() expect datum to be a vector, but it is a {}.", this->type_name());
1646 template<
bool P=HasLargeObjects, std::enable_if_t<P,
int> = 0>
1647 typename vector::const_iterator vector_end() const noexcept{
1648 if (is_phy_vector_ptr()) {
1649 return get_pointer<datum_impl::vector>()->end();
1651 TTAURI_THROW_INVALID_OPERATION_ERROR(
"vector_end() expect datum to be a vector, but it is a {}.", this->type_name());
1655 size_t hash() const noexcept{
1656 if (is_phy_float()) {
1658 }
else if (tt_unlikely(is_phy_pointer())) {
1659 switch (type_id()) {
1660 case phy_string_ptr_id:
1662 case phy_url_ptr_id:
1664 case phy_vector_ptr_id:
1665 return std::accumulate(vector_begin(), vector_end(),
size_t{0}, [](
size_t a,
auto x) {
1666 return a ^ x.hash();
1668 case phy_map_ptr_id:
1669 return std::accumulate(map_begin(), map_end(),
size_t{0}, [](
size_t a,
auto x) {
1670 return a ^ (x.first.hash() ^ x.second.hash());
1672 case phy_decimal_ptr_id:
1674 default: tt_no_default;
1681 datum_impl &operator++() {
1682 if (!this->is_numeric()) {
1683 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't increment '++' value {} of type {}",
1684 this->repr(), this->type_name()
1691 datum_impl &operator--() {
1692 if (!this->is_numeric()) {
1693 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't increment '--' value {} of type {}",
1694 this->repr(), this->type_name()
1701 datum_impl operator++(
int) {
1707 datum_impl operator--(
int) {
1713 datum_impl &operator+=(datum_impl
const &rhs) {
1714 if (this->is_vector()) {
1715 this->push_back(rhs);
1717 *
this = *
this + rhs;
1722 datum_impl &operator-=(datum_impl
const &rhs) {
1723 return *
this = *
this - rhs;
1726 datum_impl &operator*=(datum_impl
const &rhs) {
1727 return *
this = *
this * rhs;
1730 datum_impl &operator/=(datum_impl
const &rhs) {
1731 return *
this = *
this / rhs;
1734 datum_impl &operator%=(datum_impl
const &rhs) {
1735 return *
this = *
this % rhs;
1738 datum_impl &operator<<=(datum_impl
const &rhs) {
1739 return *
this = *
this << rhs;
1742 datum_impl &operator>>=(datum_impl
const &rhs) {
1743 return *
this = *
this >> rhs;
1746 datum_impl &operator&=(datum_impl
const &rhs) {
1747 return *
this = *
this & rhs;
1750 datum_impl &operator|=(datum_impl
const &rhs) {
1751 return *
this = *
this | rhs;
1754 datum_impl &operator^=(datum_impl
const &rhs) {
1755 return *
this = *
this ^ rhs;
1758 friend datum_impl operator~(datum_impl
const &rhs) {
1759 if (rhs.is_integer()) {
1760 return datum_impl{~static_cast<int64_t>(rhs)};
1762 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't bit-wise negate '~' value {} of type {}",
1763 rhs.repr(), rhs.type_name()
1768 friend datum_impl operator-(datum_impl
const &rhs) {
1769 if (rhs.is_integer()) {
1770 return datum_impl{-
static_cast<int64_t
>(rhs)};
1771 }
else if (rhs.is_decimal()) {
1772 return datum_impl{-
static_cast<decimal
>(rhs)};
1773 }
else if (rhs.is_float()) {
1774 return datum_impl{-
static_cast<double>(rhs)};
1776 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't arithmetic negate '-' value {} of type {}",
1777 rhs.repr(), rhs.type_name()
1782 friend datum_impl operator+(datum_impl
const &rhs) {
1783 if (rhs.is_numeric()) {
1786 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't arithmetic posgate '+' value {} of type {}",
1787 rhs.repr(), rhs.type_name()
1792 friend bool operator==(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1793 switch (lhs.type_id()) {
1794 case datum_impl::phy_small_id:
1795 return rhs.is_phy_small() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1796 case datum_impl::phy_integer_id0:
1797 case datum_impl::phy_integer_id1:
1798 case datum_impl::phy_integer_id2:
1799 case datum_impl::phy_integer_id3:
1800 case datum_impl::phy_integer_id4:
1801 case datum_impl::phy_integer_id5:
1802 case datum_impl::phy_integer_id6:
1803 case datum_impl::phy_integer_id7:
1804 case datum_impl::phy_integer_ptr_id:
1806 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1807 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1808 (rhs.is_integer() &&
static_cast<int64_t
>(lhs) ==
static_cast<int64_t
>(rhs))
1810 case datum_impl::phy_decimal_id:
1811 case datum_impl::phy_decimal_ptr_id:
1813 (rhs.is_float() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs)) ||
1814 (rhs.is_decimal() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs)) ||
1815 (rhs.is_integer() &&
static_cast<decimal
>(lhs) ==
static_cast<decimal
>(rhs))
1817 case datum_impl::phy_ymd_id:
1818 return rhs.is_ymd() && lhs.get_unsigned_integer() == rhs.get_unsigned_integer();
1819 case datum_impl::phy_string_id0:
1820 case datum_impl::phy_string_id1:
1821 case datum_impl::phy_string_id2:
1822 case datum_impl::phy_string_id3:
1823 case datum_impl::phy_string_id4:
1824 case datum_impl::phy_string_id5:
1825 case datum_impl::phy_string_id6:
1826 case datum_impl::phy_string_ptr_id:
1829 (rhs.is_url() &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs))
1831 case datum_impl::phy_url_ptr_id:
1832 return (rhs.is_url() || rhs.is_string()) &&
static_cast<URL
>(lhs) ==
static_cast<URL
>(rhs);
1833 case datum_impl::phy_vector_ptr_id:
1834 return rhs.is_vector() && *lhs.get_pointer<datum_impl::vector>() == *rhs.get_pointer<datum_impl::vector>();
1835 case datum_impl::phy_map_ptr_id:
1836 return rhs.is_map() && *lhs.get_pointer<datum_impl::map>() == *rhs.get_pointer<datum_impl::map>();
1838 if (lhs.is_phy_float()) {
1839 return rhs.is_numeric() &&
static_cast<double>(lhs) ==
static_cast<double>(rhs);
1846 friend bool operator<(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1847 switch (lhs.type_id()) {
1848 case datum_impl::phy_small_id:
1849 if (lhs.is_bool() && rhs.is_bool()) {
1850 return static_cast<bool>(lhs) <
static_cast<bool>(rhs);
1852 return lhs.get_unsigned_integer() < rhs.get_unsigned_integer();
1854 case datum_impl::phy_integer_id0:
1855 case datum_impl::phy_integer_id1:
1856 case datum_impl::phy_integer_id2:
1857 case datum_impl::phy_integer_id3:
1858 case datum_impl::phy_integer_id4:
1859 case datum_impl::phy_integer_id5:
1860 case datum_impl::phy_integer_id6:
1861 case datum_impl::phy_integer_id7:
1862 case datum_impl::phy_integer_ptr_id:
1863 if (rhs.is_float()) {
1864 return static_cast<double>(lhs) <
static_cast<double>(rhs);
1865 }
else if (rhs.is_decimal()) {
1866 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
1867 }
else if (rhs.is_integer()) {
1868 return static_cast<int64_t
>(lhs) <
static_cast<int64_t
>(rhs);
1870 return lhs.type_order() < rhs.type_order();
1872 case datum_impl::phy_decimal_id:
1873 case datum_impl::phy_decimal_ptr_id:
1874 if (rhs.is_float()) {
1875 return static_cast<double>(lhs) <
static_cast<double>(rhs);
1876 }
else if (rhs.is_decimal()) {
1877 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
1878 }
else if (rhs.is_integer()) {
1879 return static_cast<decimal
>(lhs) <
static_cast<decimal
>(rhs);
1881 return lhs.type_order() < rhs.type_order();
1883 case datum_impl::phy_ymd_id:
1885 return static_cast<date::year_month_day
>(lhs) <
static_cast<date::year_month_day
>(rhs);
1887 return lhs.type_order() < rhs.type_order();
1889 case datum_impl::phy_string_id0:
1890 case datum_impl::phy_string_id1:
1891 case datum_impl::phy_string_id2:
1892 case datum_impl::phy_string_id3:
1893 case datum_impl::phy_string_id4:
1894 case datum_impl::phy_string_id5:
1895 case datum_impl::phy_string_id6:
1896 case datum_impl::phy_string_ptr_id:
1897 if (rhs.is_string()) {
1899 }
else if (rhs.is_url()) {
1900 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
1902 return lhs.type_order() < rhs.type_order();
1904 case datum_impl::phy_url_ptr_id:
1905 if (rhs.is_url() || rhs.is_string()) {
1906 return static_cast<URL
>(lhs) <
static_cast<URL
>(rhs);
1908 return lhs.type_order() < rhs.type_order();
1910 case datum_impl::phy_vector_ptr_id:
1911 if (rhs.is_vector()) {
1912 return *lhs.get_pointer<datum_impl::vector>() < *rhs.get_pointer<datum_impl::vector>();
1914 return lhs.type_order() < rhs.type_order();
1916 case datum_impl::phy_map_ptr_id:
1918 return *lhs.get_pointer<datum_impl::map>() < *rhs.get_pointer<datum_impl::map>();
1920 return lhs.type_order() < rhs.type_order();
1923 if (lhs.is_phy_float()) {
1924 if (rhs.is_numeric()) {
1925 return static_cast<double>(lhs) <
static_cast<double>(rhs);
1927 return lhs.type_order() < rhs.type_order();
1935 friend bool operator!=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1936 return !(lhs == rhs);
1939 friend bool operator>(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1943 friend bool operator<=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1944 return !(rhs < lhs);
1947 friend bool operator>=(datum_impl
const &lhs, datum_impl
const &rhs)
noexcept {
1948 return !(lhs < rhs);
1951 friend datum_impl operator+(datum_impl
const &lhs, datum_impl
const &rhs) {
1952 if (lhs.is_float() || rhs.is_float()) {
1953 ttlet lhs_ =
static_cast<double>(lhs);
1954 ttlet rhs_ =
static_cast<double>(rhs);
1955 return datum_impl{ lhs_ + rhs_ };
1957 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
1958 ttlet lhs_ =
static_cast<decimal
>(lhs);
1959 ttlet rhs_ =
static_cast<decimal
>(rhs);
1960 return datum_impl{lhs_ + rhs_};
1962 }
else if (lhs.is_integer() || rhs.is_integer()) {
1963 ttlet lhs_ =
static_cast<long long int>(lhs);
1964 ttlet rhs_ =
static_cast<long long int>(rhs);
1965 return datum_impl{ lhs_ + rhs_ };
1967 }
else if (lhs.is_string() && rhs.is_string()) {
1970 return datum_impl{
std::move(lhs_ + rhs_)};
1972 }
else if (lhs.is_vector() && rhs.is_vector()) {
1973 auto lhs_ =
static_cast<datum_impl::vector
>(lhs);
1974 ttlet &rhs_ = *(rhs.get_pointer<datum_impl::vector>());
1978 }
else if (lhs.is_map() && rhs.is_map()) {
1979 ttlet &lhs_ = *(lhs.get_pointer<datum_impl::map>());
1980 auto rhs_ =
static_cast<datum_impl::map
>(rhs);
1981 for (ttlet &
item: lhs_) {
1982 rhs_.try_emplace(
item.first,
item.second);
1987 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't add '+' value {} of type {} to value {} of type {}",
1988 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
1993 friend datum_impl operator-(datum_impl
const &lhs, datum_impl
const &rhs) {
1994 if (lhs.is_float() || rhs.is_float()) {
1995 ttlet lhs_ =
static_cast<double>(lhs);
1996 ttlet rhs_ =
static_cast<double>(rhs);
1997 return datum_impl{ lhs_ - rhs_ };
1999 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2000 ttlet lhs_ =
static_cast<decimal
>(lhs);
2001 ttlet rhs_ =
static_cast<decimal
>(rhs);
2002 return datum_impl{ lhs_ - rhs_ };
2004 }
else if (lhs.is_integer() || rhs.is_integer()) {
2005 ttlet lhs_ =
static_cast<long long int>(lhs);
2006 ttlet rhs_ =
static_cast<long long int>(rhs);
2007 return datum_impl{ lhs_ - rhs_ };
2010 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't subtract '-' value {} of type {} from value {} of type {}",
2011 rhs.repr(), rhs.type_name(), lhs.repr(), lhs.type_name()
2016 friend datum_impl operator*(datum_impl
const &lhs, datum_impl
const &rhs) {
2017 if (lhs.is_float() || rhs.is_float()) {
2018 ttlet lhs_ =
static_cast<double>(lhs);
2019 ttlet rhs_ =
static_cast<double>(rhs);
2020 return datum_impl{ lhs_ * rhs_ };
2022 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2023 ttlet lhs_ =
static_cast<decimal
>(lhs);
2024 ttlet rhs_ =
static_cast<decimal
>(rhs);
2025 return datum_impl{ lhs_ * rhs_ };
2027 }
else if (lhs.is_integer() || rhs.is_integer()) {
2028 ttlet lhs_ =
static_cast<long long int>(lhs);
2029 ttlet rhs_ =
static_cast<long long int>(rhs);
2030 return datum_impl{ lhs_ * rhs_ };
2033 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't multiply '*' value {} of type {} with value {} of type {}",
2034 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2039 friend datum_impl operator/(datum_impl
const &lhs, datum_impl
const &rhs) {
2040 if (lhs.is_float() || rhs.is_float()) {
2041 ttlet lhs_ =
static_cast<double>(lhs);
2042 ttlet rhs_ =
static_cast<double>(rhs);
2043 return datum_impl{ lhs_ / rhs_ };
2045 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2046 ttlet lhs_ =
static_cast<decimal
>(lhs);
2047 ttlet rhs_ =
static_cast<decimal
>(rhs);
2048 return datum_impl{ lhs_ / rhs_ };
2050 }
else if (lhs.is_integer() || rhs.is_integer()) {
2051 ttlet lhs_ =
static_cast<long long int>(lhs);
2052 ttlet rhs_ =
static_cast<long long int>(rhs);
2053 return datum_impl{ lhs_ / rhs_ };
2055 }
else if (lhs.is_url() && (rhs.is_url() || rhs.is_string())) {
2056 ttlet lhs_ =
static_cast<URL
>(lhs);
2057 ttlet rhs_ =
static_cast<URL
>(rhs);
2058 return datum_impl{ lhs_ / rhs_ };
2061 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't divide '/' value {} of type {} by value {} of type {}",
2062 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2067 friend datum_impl operator%(datum_impl
const &lhs, datum_impl
const &rhs) {
2068 if (lhs.is_float() || rhs.is_float()) {
2069 ttlet lhs_ =
static_cast<double>(lhs);
2070 ttlet rhs_ =
static_cast<double>(rhs);
2071 return datum_impl{
fmod(lhs_, rhs_) };
2073 }
else if (lhs.is_decimal() || rhs.is_decimal()) {
2074 ttlet lhs_ =
static_cast<decimal
>(lhs);
2075 ttlet rhs_ =
static_cast<decimal
>(rhs);
2076 return datum_impl{ lhs_ % rhs_ };
2078 }
else if (lhs.is_integer() || rhs.is_integer()) {
2079 ttlet lhs_ =
static_cast<long long int>(lhs);
2080 ttlet rhs_ =
static_cast<long long int>(rhs);
2081 return datum_impl{ lhs_ % rhs_ };
2084 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't take modulo '%' value {} of type {} by value {} of type {}",
2085 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2090 friend datum_impl operator<<(datum_impl
const &lhs, datum_impl
const &rhs) {
2091 if (lhs.is_integer() && rhs.is_integer()) {
2092 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2093 ttlet rhs_ =
static_cast<int64_t
>(rhs);
2095 return datum_impl{0};
2096 }
else if (rhs_ < 0) {
2098 return datum_impl{lhs_ >> -rhs_};
2099 }
else if (rhs_ == 0) {
2101 }
else if (rhs_ > 63) {
2102 return datum_impl{0};
2104 return datum_impl{lhs_ << rhs_};
2108 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't logical shift-left '<<' value {} of type {} with value {} of type {}",
2109 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2114 friend datum_impl operator>>(datum_impl
const &lhs, datum_impl
const &rhs) {
2115 if (lhs.is_integer() && rhs.is_integer()) {
2116 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2117 ttlet rhs_ =
static_cast<int64_t
>(rhs);
2119 return datum_impl{0};
2120 }
else if (rhs_ < 0) {
2121 return datum_impl{lhs_ << -rhs_};
2122 }
else if (rhs_ == 0) {
2124 }
else if (rhs_ > 63) {
2125 return (lhs_ >= 0) ? datum_impl{0} : datum_impl{-1};
2127 return datum_impl{
static_cast<int64_t
>(lhs_) >> rhs_};
2131 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't arithmetic shift-right '>>' value {} of type {} with value {} of type {}",
2132 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2137 friend datum_impl operator&(datum_impl
const &lhs, datum_impl
const &rhs) {
2138 if (lhs.is_integer() && rhs.is_integer()) {
2139 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2140 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2141 return datum_impl{lhs_ & rhs_};
2144 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't AND '&' value {} of type {} with value {} of type {}",
2145 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2150 friend datum_impl operator|(datum_impl
const &lhs, datum_impl
const &rhs) {
2151 if (lhs.is_integer() && rhs.is_integer()) {
2152 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2153 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2154 return datum_impl{lhs_ | rhs_};
2157 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't OR '|' value {} of type {} with value {} of type {}",
2158 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2163 friend datum_impl operator^(datum_impl
const &lhs, datum_impl
const &rhs) {
2164 if (lhs.is_integer() && rhs.is_integer()) {
2165 ttlet lhs_ =
static_cast<uint64_t
>(lhs);
2166 ttlet rhs_ =
static_cast<uint64_t
>(rhs);
2167 return datum_impl{lhs_ ^ rhs_};
2170 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't XOR '^' value {} of type {} with value {} of type {}",
2171 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2176 friend std::string to_string(datum_impl
const &d) {
2181 return os << static_cast<std::string>(d);
2184 friend void swap(datum_impl &lhs, datum_impl &rhs)
noexcept {
2188 friend datum_impl pow(datum_impl
const &lhs, datum_impl
const &rhs) {
2189 if (lhs.is_numeric() || rhs.is_numeric()) {
2190 ttlet lhs_ =
static_cast<double>(lhs);
2191 ttlet rhs_ =
static_cast<double>(rhs);
2192 return datum_impl{
std::pow(lhs_, rhs_) };
2195 TTAURI_THROW_INVALID_OPERATION_ERROR(
"Can't raise to a power '**' value {} of type {} with value {} of type {}",
2196 lhs.repr(), lhs.type_name(), rhs.repr(), rhs.type_name()
2211 if (lhs.is_map() && rhs.is_map()) {
2215 for (
auto rhs_i = rhs.map_begin(); rhs_i != rhs.map_end(); rhs_i++) {
2216 auto result_i = result_map->
find(rhs_i->first);
2217 if (result_i == result_map->end()) {
2218 result_map->insert(*rhs_i);
2220 result_i->second =
deep_merge(result_i->second, rhs_i->second);
2224 }
else if (lhs.is_vector() && rhs.is_vector()) {
2228 for (
auto rhs_i = rhs.vector_begin(); rhs_i != rhs.vector_end(); rhs_i++) {