239 template<
typename To>
243 if (holds_alternative<To>(lhs) and holds_alternative<To>(rhs)) {
244 r.set(get<To>(lhs), get<To>(rhs));
246 }
else if (holds_alternative<To>(lhs) and promotable_to<To>(rhs)) {
247 r.set(get<To>(lhs),
static_cast<To
>(rhs));
249 }
else if (promotable_to<To>(lhs) and holds_alternative<To>(rhs)) {
250 r.set(
static_cast<To
>(lhs), get<To>(rhs));
256 constexpr ~datum() noexcept
261 constexpr datum(datum
const& other) noexcept : _tag(other._tag), _value(other._value)
263 if (other.is_pointer()) {
268 constexpr datum(datum&& other) noexcept : _tag(other._tag), _value(other._value)
270 other._tag = tag_type::monostate;
271 other._value._long_long = 0;
274 constexpr datum() noexcept : _tag(tag_type::monostate), _value(0) {}
275 constexpr explicit datum(std::monostate) noexcept : _tag(tag_type::monostate), _value(0) {}
276 constexpr explicit datum(nullptr_t) noexcept : _tag(tag_type::null), _value(0) {}
277 constexpr explicit datum(continue_type) noexcept : _tag(tag_type::flow_continue), _value(0) {}
278 constexpr explicit datum(break_type) noexcept : _tag(tag_type::flow_break), _value(0) {}
279 constexpr explicit datum(
bool value) noexcept : _tag(tag_type::boolean), _value(value) {}
280 constexpr explicit datum(std::floating_point
auto value) noexcept :
281 _tag(tag_type::floating_point), _value(narrow_cast<double>(value))
285 constexpr explicit datum(numeric_integral
auto value) noexcept :
286 _tag(tag_type::integral), _value(narrow_cast<long long>(value))
290 constexpr explicit datum(decimal value) noexcept : _tag(tag_type::decimal), _value(value) {}
291 constexpr explicit datum(std::chrono::year_month_day value) noexcept : _tag(tag_type::year_month_day), _value(value) {}
293 explicit datum(std::string_view value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
294 explicit datum(
char const *value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
295 explicit datum(vector_type value) noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
296 explicit datum(map_type value) noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
297 explicit datum(bstring value) noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
299 template<
typename... Args>
300 [[nodiscard]]
static datum
make_vector(Args
const&...args)
noexcept
302 return datum{vector_type{datum{args}...}};
305 template<
typename Key,
typename Value,
typename... Args>
306 static void populate_map(map_type& r, Key
const& key, Value
const& value, Args
const&...args)
noexcept
309 if constexpr (
sizeof...(Args) > 0) {
310 populate_map(r, args...);
314 template<
typename... Args>
315 [[nodiscard]]
static datum make_map(Args
const&...args)
noexcept
317 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
320 if constexpr (
sizeof...(Args) > 0) {
321 populate_map(r, args...);
326 [[nodiscard]]
static datum make_break() noexcept
328 return datum{break_type{}};
331 [[nodiscard]]
static datum make_continue() noexcept
333 return datum{continue_type{}};
336 constexpr datum& operator=(datum
const& other)
noexcept
338 hi_return_on_self_assignment(other);
342 _value = other._value;
343 if (other.is_pointer()) {
349 constexpr datum& operator=(datum&& other)
noexcept
356 constexpr datum& operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
359 _tag = tag_type::floating_point;
360 _value =
static_cast<double>(value);
364 constexpr datum& operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
367 _tag = tag_type::integral;
368 _value =
static_cast<long long>(value);
372 constexpr datum& operator=(decimal value)
375 _tag = tag_type::decimal;
379 constexpr datum& operator=(
bool value)
noexcept
382 _tag = tag_type::boolean;
387 constexpr datum& operator=(std::chrono::year_month_day value)
noexcept
390 _tag = tag_type::year_month_day;
395 constexpr datum& operator=(std::monostate)
noexcept
398 _tag = tag_type::monostate;
403 constexpr datum& operator=(nullptr_t)
noexcept
406 _tag = tag_type::null;
414 _tag = tag_type::string;
419 datum& operator=(
char const *value)
noexcept
422 _tag = tag_type::string;
427 datum& operator=(std::string_view value)
noexcept
430 _tag = tag_type::string;
435 datum& operator=(vector_type value)
noexcept
438 _tag = tag_type::vector;
439 _value =
new vector_type{
std::move(value)};
443 datum& operator=(map_type value)
noexcept
446 _tag = tag_type::map;
451 datum& operator=(bstring value)
noexcept
454 _tag = tag_type::bstring;
459 constexpr explicit operator bool() const noexcept
462 case tag_type::floating_point:
463 return to_bool(get<double>(*
this));
464 case tag_type::decimal:
465 return to_bool(get<decimal>(*
this));
466 case tag_type::boolean:
467 return get<bool>(*
this);
468 case tag_type::integral:
469 return to_bool(get<long long>(*
this));
470 case tag_type::year_month_day:
472 case tag_type::string:
473 return not get<std::string>(*this).empty();
474 case tag_type::vector:
475 return not get<vector_type>(*this).empty();
477 return not get<map_type>(*this).empty();
478 case tag_type::bstring:
479 return not get<bstring>(*this).empty();
485 [[nodiscard]]
constexpr bool empty()
const
488 case tag_type::string:
489 return get<std::string>(*this).empty();
490 case tag_type::vector:
491 return get<vector_type>(*this).empty();
493 return get<map_type>(*this).empty();
494 case tag_type::bstring:
495 return get<bstring>(*this).empty();
497 throw std::domain_error(std::format(
"Type {} can not be checked for empty", *
this));
501 template<std::
floating_po
int T>
502 constexpr explicit operator T()
const
505 case tag_type::floating_point:
506 return static_cast<T
>(get<double>(*
this));
507 case tag_type::integral:
508 return static_cast<T
>(get<long long>(*
this));
509 case tag_type::decimal:
510 return static_cast<T
>(get<decimal>(*
this));
511 case tag_type::boolean:
512 return static_cast<T
>(get<bool>(*
this));
514 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
518 constexpr explicit operator decimal()
const
521 case tag_type::floating_point:
522 return decimal(get<double>(*
this));
523 case tag_type::integral:
524 return decimal(get<long long>(*
this));
525 case tag_type::decimal:
526 return get<decimal>(*
this);
527 case tag_type::boolean:
528 return decimal(get<bool>(*
this));
530 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
534 template<numeric_
integral T>
535 constexpr explicit operator T()
const
537 if (
auto f = get_if<double>(*
this)) {
544 return narrow_cast<T>(r);
546 }
else if (
auto i = get_if<long long>(*
this)) {
550 return narrow_cast<T>(*i);
552 }
else if (
auto d = get_if<decimal>(*
this)) {
553 hilet r =
static_cast<long long>(*d);
557 return narrow_cast<T>(r);
559 }
else if (
auto b = get_if<bool>(*
this)) {
560 return narrow_cast<T>(*b);
563 throw std::domain_error(std::format(
"Can't convert {} to an integral", repr(*
this)));
567 constexpr explicit operator std::chrono::year_month_day()
const
569 if (
auto ymd = get_if<std::chrono::year_month_day>(*
this)) {
572 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day", repr(*
this)));
579 case tag_type::monostate:
581 case tag_type::floating_point:
583 case tag_type::decimal:
585 case tag_type::integral:
587 case tag_type::boolean:
588 return _value._bool ?
"true" :
"false";
589 case tag_type::year_month_day:
590 return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
593 case tag_type::flow_break:
595 case tag_type::flow_continue:
597 case tag_type::string:
598 return *_value._string;
599 case tag_type::vector:
602 for (
hilet& item : *_value._vector) {
612 for (
hilet& item : *_value._map) {
613 r += repr(item.first);
615 r += repr(item.second);
621 case tag_type::bstring:
622 return base64::encode(*_value._bstring);
628 explicit operator std::string_view()
const
630 if (
auto s = get_if<std::string>(*
this)) {
631 return std::string_view{*s};
633 throw std::domain_error(std::format(
"Can't convert {} to an std::string_view", repr(*
this)));
637 explicit operator vector_type()
const
639 if (
auto v = get_if<vector_type>(*
this)) {
642 throw std::domain_error(std::format(
"Can't convert {} to an vector", repr(*
this)));
646 explicit operator map_type()
const
648 if (
auto m = get_if<map_type>(*
this)) {
655 explicit operator bstring()
const
658 if (_tag != tag_type::bstring) {
659 throw std::domain_error(std::format(
"Can't convert {} to an bstring", repr(*
this)));
661 return get<bstring>(*
this);
664 [[nodiscard]]
constexpr char const *type_name() const noexcept
667 case tag_type::floating_point:
669 case tag_type::decimal:
671 case tag_type::integral:
673 case tag_type::boolean:
675 case tag_type::year_month_day:
677 case tag_type::string:
679 case tag_type::vector:
683 case tag_type::bstring:
694 return _tag == tag_type::monostate;
700 [[nodiscard]]
constexpr bool is_break() const noexcept
702 return _tag == tag_type::flow_break;
710 return _tag == tag_type::flow_continue;
716 case tag_type::floating_point:
718 case tag_type::decimal:
720 case tag_type::integral:
722 case tag_type::boolean:
724 case tag_type::year_month_day:
727 r |= narrow_cast<uint32_t>(
static_cast<int>(_value._year_month_day.year())) << 16;
728 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.month())) << 8;
729 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.day()));
732 case tag_type::string:
734 case tag_type::vector:
737 for (
hilet& v : *_value._vector) {
738 r = hash_mix(r, v.hash());
745 for (
hilet& kv : *_value._map) {
746 r = hash_mix(r, kv.first.hash(), kv.second.hash());
750 case tag_type::bstring:
759 if (
hilet *s = get_if<std::string>(*
this)) {
761 }
else if (
hilet *v = get_if<vector_type>(*
this)) {
763 }
else if (
hilet *m = get_if<map_type>(*
this)) {
765 }
else if (
hilet *b = get_if<bstring>(*
this)) {
772 [[nodiscard]]
constexpr friend std::size_t size(datum
const& rhs)
777 [[nodiscard]]
constexpr datum
const& back()
const
779 if (
hilet *v = get_if<vector_type>(*
this)) {
789 [[nodiscard]]
constexpr datum& back()
791 if (
auto *v = get_if<vector_type>(*
this)) {
801 [[nodiscard]]
constexpr datum
const& front()
const
803 if (
hilet *v = get_if<vector_type>(*
this)) {
809 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
813 [[nodiscard]]
constexpr datum& front()
815 if (
auto *v = get_if<vector_type>(*
this)) {
821 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
825 [[nodiscard]]
constexpr auto cbegin()
const
827 if (
hilet *v = get_if<vector_type>(*
this)) {
830 throw std::domain_error(std::format(
"Can not evaluate {}.cbegin()", repr(*
this)));
834 [[nodiscard]]
constexpr auto begin()
const
836 if (
hilet *v = get_if<vector_type>(*
this)) {
839 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
843 [[nodiscard]]
constexpr auto begin()
845 if (
hilet *v = get_if<vector_type>(*
this)) {
848 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
852 [[nodiscard]]
constexpr auto cend()
const
854 if (
hilet *v = get_if<vector_type>(*
this)) {
861 [[nodiscard]]
constexpr auto end()
const
863 if (
hilet *v = get_if<vector_type>(*
this)) {
870 [[nodiscard]]
constexpr auto end()
872 if (
hilet *v = get_if<vector_type>(*
this)) {
883 if (
hilet *
m = get_if<map_type>(*
this)) {
887 r.push_back(kv.first);
899 if (
hilet *
m = get_if<map_type>(*
this)) {
903 r.push_back(kv.second);
907 throw std::domain_error(std::format(
"Can not evaluate {}.values()", repr(*
this)));
915 if (
hilet *
m = get_if<map_type>(*
this)) {
924 throw std::domain_error(std::format(
"Can not evaluate {}.items()", repr(*
this)));
928 constexpr void push_back(
datum const& rhs)
930 if (
auto *v = get_if<vector_type>(*
this)) {
931 return v->push_back(rhs);
933 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
937 constexpr void push_back(datum&& rhs)
939 if (
auto *v = get_if<vector_type>(*
this)) {
942 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
946 template<
typename Arg>
947 constexpr void push_back(Arg&& arg)
949 push_back(datum{std::forward<Arg>(arg)});
952 constexpr void pop_back()
954 if (
auto *v = get_if<vector_type>(*
this)) {
958 return v->pop_back();
960 throw std::domain_error(std::format(
"Can not evaluate {}.pop_back()", repr(*
this)));
964 [[nodiscard]]
constexpr bool contains(datum
const& rhs)
const
966 if (
auto *m = get_if<map_type>(*
this)) {
967 return m->contains(rhs);
969 throw std::domain_error(std::format(
"Can not evaluate {}.contains({})", repr(*
this), repr(rhs)));
973 template<
typename Arg>
974 [[nodiscard]]
constexpr bool contains(Arg
const& arg)
const
976 return contains(datum{arg});
982 find(path.cbegin(), path.cend(), r);
989 const_cast<datum *
>(
this)->
find(path.cbegin(), path.cend(), tmp);
1005 return to_bool(remove(path.cbegin(), path.cend()));
1016 return find_one(path.cbegin(), path.cend(),
false);
1027 return find_one(path.cbegin(), path.cend(),
true);
1038 return const_cast<datum *
>(
this)->find_one(path.cbegin(), path.cend(),
false);
1041 [[nodiscard]]
datum const& operator[](
datum const& rhs)
const
1043 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1044 hilet& v = get<vector_type>(*
this);
1046 auto index = get<long long>(rhs);
1048 index = ssize(v) + index;
1050 if (index < 0 or index >= ssize(v)) {
1056 }
else if (holds_alternative<map_type>(*
this)) {
1057 hilet&
m = get<map_type>(*
this);
1059 if (it ==
m.end()) {
1066 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1070 [[nodiscard]]
constexpr datum& operator[](datum
const& rhs)
1072 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1073 auto& v = get<vector_type>(*
this);
1075 auto index = get<long long>(rhs);
1077 index = ssize(v) + index;
1079 if (index < 0 or index >= ssize(v)) {
1085 }
else if (holds_alternative<map_type>(*
this)) {
1086 auto&
m = get<map_type>(*
this);
1090 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1094 [[nodiscard]]
constexpr datum
const& operator[](
auto const& rhs)
const
1096 return (*
this)[datum{rhs}];
1099 [[nodiscard]]
constexpr datum& operator[](
auto const& rhs)
1101 return (*
this)[datum{rhs}];
1104 [[nodiscard]]
constexpr datum& operator++()
1106 if (holds_alternative<long long>(*
this)) {
1107 ++_value._long_long;
1114 [[nodiscard]]
constexpr datum& operator--()
1116 if (holds_alternative<long long>(*
this)) {
1117 --_value._long_long;
1124 [[nodiscard]]
constexpr datum operator++(
int)
1126 if (holds_alternative<long long>(*
this)) {
1128 _value._long_long++;
1134 [[nodiscard]]
constexpr datum operator--(
int)
1136 if (holds_alternative<long long>(*
this)) {
1138 _value._long_long--;
1145 constexpr datum& operator+=(
auto const& rhs)
1147 if (holds_alternative<vector_type>(*
this)) {
1151 return (*
this) = (*this) + rhs;
1155#define X(op, inner_op) \
1156 constexpr datum& operator op(auto const& rhs) \
1158 return (*this) = (*this)inner_op rhs; \
1172 [[nodiscard]]
friend constexpr bool operator==(datum
const& lhs, datum
const& rhs)
noexcept
1174 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1175 return doubles.lhs() == doubles.rhs();
1177 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1178 return decimals.lhs() == decimals.rhs();
1180 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1181 return long_longs.lhs() == long_longs.rhs();
1183 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1184 return bools.lhs() == bools.rhs();
1186 }
else if (
hilet ymds = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1187 return ymds.lhs() == ymds.rhs();
1189 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1190 return strings.lhs() == strings.rhs();
1192 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1193 return vectors.lhs() == vectors.rhs();
1195 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1196 return maps.lhs() == maps.rhs();
1199 return lhs._tag == rhs._tag;
1231 [[nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const& lhs, datum
const& rhs)
noexcept
1233 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1234 return doubles.lhs() <=> doubles.rhs();
1236 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1237 return decimals.lhs() <=> decimals.rhs();
1239 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1240 return long_longs.lhs() <=> long_longs.rhs();
1242 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1243 return bools.lhs() <=> bools.rhs();
1245 }
else if (
hilet year_month_days = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1246 return year_month_days.lhs() <=> year_month_days.rhs();
1248 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1249 return strings.lhs() <=> strings.rhs();
1251 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1252 return vectors.lhs() <=> vectors.rhs();
1254 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1255 return maps.lhs() <=> maps.rhs();
1257 }
else if (
hilet bstrings = promote_if<bstring>(lhs, rhs)) {
1258 return bstrings.lhs() <=> bstrings.rhs();
1261 return lhs._tag <=> rhs._tag;
1275 [[nodiscard]]
friend constexpr datum operator-(datum
const& rhs)
1277 if (
hilet rhs_double = get_if<double>(rhs)) {
1278 return datum{-*rhs_double};
1280 }
else if (
hilet rhs_decimal = get_if<decimal>(rhs)) {
1281 return datum{-*rhs_decimal};
1283 }
else if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1284 return datum{-*rhs_long_long};
1300 [[nodiscard]]
friend constexpr datum operator~(datum
const& rhs)
1302 if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1303 return datum{~*rhs_long_long};
1324 [[nodiscard]]
friend constexpr datum operator+(datum
const& lhs, datum
const& rhs)
1326 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1327 return datum{doubles.lhs() + doubles.rhs()};
1329 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1330 return datum{decimals.lhs() + decimals.rhs()};
1332 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1333 return datum{long_longs.lhs() + long_longs.rhs()};
1335 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1336 return datum{strings.lhs() + strings.rhs()};
1338 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1339 auto r = vectors.lhs();
1340 r.insert(r.end(), vectors.rhs().begin(), vectors.rhs().end());
1344 throw std::domain_error(std::format(
"Can not evaluate {} '+' {}", repr(lhs), repr(rhs)));
1359 [[nodiscard]]
friend constexpr datum operator-(datum
const& lhs, datum
const& rhs)
1361 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1362 return datum{doubles.lhs() - doubles.rhs()};
1364 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1365 return datum{decimals.lhs() - decimals.rhs()};
1367 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1368 return datum{long_longs.lhs() - long_longs.rhs()};
1371 throw std::domain_error(std::format(
"Can not evaluate {} '-' {}", repr(lhs), repr(rhs)));
1386 [[nodiscard]]
friend constexpr datum operator*(datum
const& lhs, datum
const& rhs)
1388 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1389 return datum{doubles.lhs() * doubles.rhs()};
1391 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1392 return datum{decimals.lhs() * decimals.rhs()};
1394 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1395 return datum{long_longs.lhs() * long_longs.rhs()};
1398 throw std::domain_error(std::format(
"Can not evaluate {} '*' {}", repr(lhs), repr(rhs)));
1413 [[nodiscard]]
friend constexpr datum operator/(datum
const& lhs, datum
const& rhs)
1415 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1416 if (doubles.rhs() == 0) {
1417 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1419 return datum{doubles.lhs() / doubles.rhs()};
1421 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1422 if (decimals.rhs() == 0) {
1423 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1425 return datum{decimals.lhs() / decimals.rhs()};
1427 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1428 if (long_longs.rhs() == 0) {
1429 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1431 return datum{long_longs.lhs() / long_longs.rhs()};
1434 throw std::domain_error(std::format(
"Can not evaluate {} '/' {}", repr(lhs), repr(rhs)));
1449 [[nodiscard]]
friend constexpr datum operator%(datum
const& lhs, datum
const& rhs)
1451 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1452 if (long_longs.rhs() == 0) {
1453 throw std::domain_error(std::format(
"Divide by zero {} '%' {}", repr(lhs), repr(rhs)));
1455 return datum{long_longs.lhs() % long_longs.rhs()};
1458 throw std::domain_error(std::format(
"Can not evaluate {} '%' {}", repr(lhs), repr(rhs)));
1472 [[nodiscard]]
friend constexpr datum
pow(datum
const& lhs, datum
const& rhs)
1474 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1475 return datum{
pow(doubles.lhs(), doubles.rhs())};
1477 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1478 return datum{
pow(long_longs.lhs(), long_longs.rhs())};
1481 throw std::domain_error(std::format(
"Can not evaluate pow({}, {})", repr(lhs), repr(rhs)));
1495 [[nodiscard]]
friend constexpr datum operator&(datum
const& lhs, datum
const& rhs)
1497 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1498 return datum{long_longs.lhs() & long_longs.rhs()};
1500 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1501 return datum{bools.lhs() and bools.rhs()};
1504 throw std::domain_error(std::format(
"Can not evaluate {} '&' {}", repr(lhs), repr(rhs)));
1518 [[nodiscard]]
friend constexpr datum operator|(datum
const& lhs, datum
const& rhs)
1520 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1521 return datum{long_longs.lhs() | long_longs.rhs()};
1523 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1524 return datum{bools.lhs() or bools.rhs()};
1527 throw std::domain_error(std::format(
"Can not evaluate {} '|' {}", repr(lhs), repr(rhs)));
1541 [[nodiscard]]
friend constexpr datum operator^(datum
const& lhs, datum
const& rhs)
1543 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1544 return datum{long_longs.lhs() ^ long_longs.rhs()};
1546 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1547 return datum{bools.lhs() != bools.rhs()};
1550 throw std::domain_error(std::format(
"Can not evaluate {} '^' {}", repr(lhs), repr(rhs)));
1566 [[nodiscard]]
friend constexpr datum operator<<(datum
const& lhs, datum
const& rhs)
1568 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1569 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1570 throw std::domain_error(std::format(
"Invalid shift count {} '<<' {}", repr(lhs), repr(rhs)));
1572 return datum{long_longs.lhs() << long_longs.rhs()};
1575 throw std::domain_error(std::format(
"Can not evaluate {} '<<' {}", repr(lhs), repr(rhs)));
1590 [[nodiscard]]
friend constexpr datum operator>>(datum
const& lhs, datum
const& rhs)
1592 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1593 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1594 throw std::domain_error(std::format(
"Invalid shift count {} '>>' {}", repr(lhs), repr(rhs)));
1596 return datum{long_longs.lhs() >> long_longs.rhs()};
1599 throw std::domain_error(std::format(
"Can not evaluate {} '>>' {}", repr(lhs), repr(rhs)));
1609 [[nodiscard]] friend constexpr auto operator op(datum const& lhs, auto const& rhs) \
1611 return lhs op datum{rhs}; \
1613 [[nodiscard]] friend constexpr auto operator op(auto const& lhs, datum const& rhs) \
1615 return datum{lhs} op rhs; \
1632 [[nodiscard]]
friend std::string repr(datum
const& rhs)
noexcept
1635 case tag_type::monostate:
1637 case tag_type::floating_point:
1638 return std::format(
"{:.1f}", rhs._value._double);
1639 case tag_type::decimal:
1641 case tag_type::integral:
1642 return std::format(
"{}", rhs._value._long_long);
1643 case tag_type::boolean:
1644 return rhs._value._bool ?
"true" :
"false";
1645 case tag_type::year_month_day:
1646 return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1647 case tag_type::null:
1649 case tag_type::flow_break:
1651 case tag_type::flow_continue:
1653 case tag_type::string:
1654 return std::format(
"\"{}\"", *rhs._value._string);
1655 case tag_type::vector:
1658 for (
hilet& item : *rhs._value._vector) {
1668 for (
hilet& item : *rhs._value._map) {
1669 r += repr(item.first);
1671 r += repr(item.second);
1677 case tag_type::bstring:
1678 return base64::encode(*rhs._value._bstring);
1697 template<
typename T>
1700 if constexpr (std::is_same_v<T, double>) {
1701 return rhs._tag == tag_type::floating_point;
1702 }
else if constexpr (std::is_same_v<T, decimal>) {
1703 return rhs._tag == tag_type::decimal;
1704 }
else if constexpr (std::is_same_v<T, long long>) {
1705 return rhs._tag == tag_type::integral;
1706 }
else if constexpr (std::is_same_v<T, bool>) {
1707 return rhs._tag == tag_type::boolean;
1708 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1709 return rhs._tag == tag_type::year_month_day;
1710 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1711 return rhs._tag == tag_type::null;
1712 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1713 return rhs._tag == tag_type::monostate;
1714 }
else if constexpr (std::is_same_v<T, break_type>) {
1715 return rhs._tag == tag_type::flow_break;
1716 }
else if constexpr (std::is_same_v<T, continue_type>) {
1717 return rhs._tag == tag_type::flow_continue;
1718 }
else if constexpr (std::is_same_v<T, std::string>) {
1719 return rhs._tag == tag_type::string;
1720 }
else if constexpr (std::is_same_v<T, vector_type>) {
1721 return rhs._tag == tag_type::vector;
1722 }
else if constexpr (std::is_same_v<T, map_type>) {
1723 return rhs._tag == tag_type::map;
1724 }
else if constexpr (std::is_same_v<T, bstring>) {
1725 return rhs._tag == tag_type::bstring;
1742 template<
typename To>
1745 if constexpr (std::is_same_v<To, double>) {
1746 return holds_alternative<double>(rhs) or holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or
1747 holds_alternative<bool>(rhs);
1748 }
else if constexpr (std::is_same_v<To, decimal>) {
1749 return holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1750 }
else if constexpr (std::is_same_v<To, long long>) {
1751 return holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1753 return holds_alternative<To>(rhs);
1765 template<
typename T>
1766 [[nodiscard]]
friend constexpr T
const&
get(
datum const& rhs)
noexcept
1768 hi_axiom(holds_alternative<T>(rhs));
1769 if constexpr (std::is_same_v<T, double>) {
1770 return rhs._value._double;
1771 }
else if constexpr (std::is_same_v<T, decimal>) {
1772 return rhs._value._decimal;
1773 }
else if constexpr (std::is_same_v<T, long long>) {
1774 return rhs._value._long_long;
1775 }
else if constexpr (std::is_same_v<T, bool>) {
1776 return rhs._value._bool;
1777 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1778 return rhs._value._year_month_day;
1779 }
else if constexpr (std::is_same_v<T, std::string>) {
1780 return *rhs._value._string;
1781 }
else if constexpr (std::is_same_v<T, vector_type>) {
1782 return *rhs._value._vector;
1783 }
else if constexpr (std::is_same_v<T, map_type>) {
1784 return *rhs._value._map;
1785 }
else if constexpr (std::is_same_v<T, bstring>) {
1786 return *rhs._value._bstring;
1800 template<
typename T>
1801 [[nodiscard]]
friend constexpr T&
get(
datum& rhs)
noexcept
1803 hi_axiom(holds_alternative<T>(rhs));
1804 if constexpr (std::is_same_v<T, double>) {
1805 return rhs._value._double;
1806 }
else if constexpr (std::is_same_v<T, decimal>) {
1807 return rhs._value._decimal;
1808 }
else if constexpr (std::is_same_v<T, long long>) {
1809 return rhs._value._long_long;
1810 }
else if constexpr (std::is_same_v<T, bool>) {
1811 return rhs._value._bool;
1812 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1813 return rhs._value._year_month_day;
1814 }
else if constexpr (std::is_same_v<T, std::string>) {
1815 return *rhs._value._string;
1816 }
else if constexpr (std::is_same_v<T, vector_type>) {
1817 return *rhs._value._vector;
1818 }
else if constexpr (std::is_same_v<T, map_type>) {
1819 return *rhs._value._map;
1820 }
else if constexpr (std::is_same_v<T, bstring>) {
1821 return *rhs._value._bstring;
1835 template<
typename T>
1838 if (holds_alternative<T>(rhs)) {
1839 return &get<T>(rhs);
1853 template<
typename T>
1854 [[nodiscard]]
friend constexpr T
const *
get_if(
datum const& rhs)
noexcept
1856 if (holds_alternative<T>(rhs)) {
1857 return &get<T>(rhs);
1872 template<
typename T>
1875 if (
auto *value = rhs.find_one(path)) {
1876 if (holds_alternative<T>(*value)) {
1877 return &get<T>(*value);
1895 template<
typename T>
1898 if (
auto *value =
const_cast<datum&
>(rhs).find_one(path)) {
1899 if (holds_alternative<T>(*value)) {
1900 return &get<T>(*value);
1910 enum class tag_type :
signed char {
1929 tag_type _tag = tag_type::monostate;
1932 long long _long_long;
1935 std::chrono::year_month_day _year_month_day;
1937 vector_type *_vector;
1941 constexpr value_type(numeric_integral
auto value) noexcept : _long_long(narrow_cast<long long>(value)) {}
1942 constexpr value_type(std::floating_point
auto value) noexcept : _double(narrow_cast<double>(value)) {}
1943 constexpr value_type(decimal value) noexcept : _decimal(value) {}
1944 constexpr value_type(
bool value) noexcept : _bool(value) {}
1945 constexpr value_type(std::chrono::year_month_day value) noexcept : _year_month_day(value) {}
1946 constexpr value_type(
std::string *value) noexcept : _string(value) {}
1947 constexpr value_type(vector_type *value) noexcept : _vector(value) {}
1948 constexpr value_type(map_type *value) noexcept : _map(value) {}
1949 constexpr value_type(bstring *value) noexcept : _bstring(value) {}
1954 [[nodiscard]]
constexpr bool is_scalar() const noexcept
1956 return to_underlying(_tag) >= 0;
1959 [[nodiscard]]
constexpr bool is_pointer() const noexcept
1961 return to_underlying(_tag) < 0;
1964 hi_no_inline
void copy_pointer(datum
const& other)
noexcept
1967 switch (other._tag) {
1968 case tag_type::string:
1969 _value._string =
new std::string{*other._value._string};
1971 case tag_type::vector:
1972 _value._vector =
new vector_type{*other._value._vector};
1975 _value._map =
new map_type{*other._value._map};
1977 case tag_type::bstring:
1978 _value._bstring =
new bstring{*other._value._bstring};
1985 hi_no_inline
void _delete_pointer() noexcept
1989 case tag_type::string:
1990 delete _value._string;
1992 case tag_type::vector:
1993 delete _value._vector;
1998 case tag_type::bstring:
1999 delete _value._bstring;
2006 constexpr void delete_pointer() noexcept
2013 void find_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2015 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2016 for (
auto& item : *vector) {
2017 item.find(it + 1, it_end, r);
2020 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2021 for (
auto& item : *map) {
2022 item.second.find(it + 1, it_end, r);
2027 void find_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2029 this->
find(it + 1, it_end, r);
2031 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2032 for (
auto& item : *vector) {
2033 item.find(it, it_end, r);
2036 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2037 for (
auto& item : *map) {
2038 item.second.find(it, it_end, r);
2044 jsonpath_indices
const& indices,
2045 jsonpath::const_iterator it,
2046 jsonpath::const_iterator it_end,
2049 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2050 for (
hilet index : indices.filter(ssize(*vector))) {
2051 (*vector)[index].find(it + 1, it_end, r);
2057 jsonpath_names
const& names,
2058 jsonpath::const_iterator it,
2059 jsonpath::const_iterator it_end,
2062 if (
auto map = get_if<datum::map_type>(*
this)) {
2063 for (
hilet& name : names) {
2064 hilet name_ = datum{name};
2065 auto jt = map->find(name_);
2066 if (jt != map->cend()) {
2067 jt->second.find(it + 1, it_end, r);
2074 jsonpath_slice
const& slice,
2075 jsonpath::const_iterator it,
2076 jsonpath::const_iterator it_end,
2079 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2080 hilet first = slice.begin(vector->size());
2081 hilet last = slice.end(vector->size());
2083 for (
auto index = first; index != last; index += slice.step) {
2084 if (index >= 0 and index < vector->size()) {
2085 (*this)[index].find(it + 1, it_end, r);
2096 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2097 find(it + 1, it_end, r);
2099 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2100 find(it + 1, it_end, r);
2102 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2103 find_wildcard(it, it_end, r);
2105 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2106 find_descend(it, it_end, r);
2108 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2109 find_indices(*indices, it, it_end, r);
2111 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2112 find_names(*names, it, it_end, r);
2114 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2115 find_slice(*slice, it, it_end, r);
2122 [[nodiscard]]
int remove_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2126 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2127 auto jt = vector->begin();
2128 while (jt != vector->end()) {
2129 hilet match = jt->remove(it + 1, it_end);
2133 jt = vector->erase(jt);
2138 return vector->empty() ? 2 : r;
2140 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2141 auto jt = map->begin();
2142 while (jt != map->end()) {
2143 hilet match = jt->second.remove(it + 1, it_end);
2147 jt = map->erase(jt);
2152 return map->empty() ? 2 : r;
2159 [[nodiscard]]
int remove_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2171 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2172 auto jt = vector->begin();
2173 while (jt != vector->end()) {
2174 hilet match = jt->remove(it, it_end);
2178 jt = vector->erase(jt);
2183 return vector->empty() ? 2 : r;
2185 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2186 auto jt = map->begin();
2187 while (jt != map->end()) {
2188 hilet match = jt->second.remove(it, it_end);
2192 jt = map->erase(jt);
2197 return map->empty() ? 2 : r;
2205 remove_indices(jsonpath_indices
const& indices, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2207 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2211 for (
hilet index : indices.filter(ssize(*vector))) {
2212 hilet match = (*vector)[index - offset].remove(it + 1, it_end);
2215 vector->erase(vector->begin() + (index - offset));
2220 return vector->empty() ? 2 : r;
2228 remove_names(jsonpath_names
const& names, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2230 if (
auto map = get_if<datum::map_type>(*
this)) {
2233 for (
hilet& name : names) {
2234 hilet name_ = datum{name};
2235 auto jt = map->find(name_);
2236 if (jt != map->cend()) {
2237 hilet match = jt->second.remove(it + 1, it_end);
2245 return map->empty() ? 2 : r;
2253 remove_slice(jsonpath_slice
const& slice, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2255 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2258 hilet first = slice.begin(vector->size());
2259 hilet last = slice.end(vector->size());
2262 for (
auto index = first; index != last; index += slice.step) {
2263 if (index >= 0 and index < vector->size()) {
2264 hilet match = (*this)[index - offset].remove(it + 1, it_end);
2268 vector->erase(vector->begin() + (index - offset));
2274 return vector->empty() ? 2 : r;
2281 [[nodiscard]]
int remove(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2287 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2288 return remove(it + 1, it_end);
2290 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2291 return remove(it + 1, it_end);
2293 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2294 return remove_wildcard(it, it_end);
2296 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2297 return remove_descend(it, it_end);
2299 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2300 return remove_indices(*indices, it, it_end);
2302 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2303 return remove_names(*names, it, it_end);
2305 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2306 return remove_slice(*slice, it, it_end);
2313 [[nodiscard]] datum *
2314 find_one_name(datum
const& name, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2316 hi_axiom(holds_alternative<std::string>(name));
2318 if (
auto *map = get_if<map_type>(*
this)) {
2319 auto i = map->find(name);
2320 if (i != map->end()) {
2321 return i->second.find_one(it + 1, it_end, create);
2323 }
else if (create) {
2324 (*map)[name] = datum{std::monostate{}};
2325 return find_one_name(name, it, it_end, create);
2331 }
else if (holds_alternative<std::monostate>(*
this) and create) {
2332 *
this = datum::make_map(name, std::monostate{});
2333 return find_one_name(name, it, it_end, create);
2340 [[nodiscard]] datum *
2341 find_one_index(
std::size_t index, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2343 if (
auto *vector = get_if<vector_type>(*
this)) {
2344 if (index < vector->size()) {
2345 return (*vector)[index].find_one(it + 1, it_end, create);
2346 }
else if (index == vector->size() and create) {
2347 vector->push_back(datum{std::monostate{}});
2348 return find_one_index(index, it, it_end, create);
2353 }
else if (holds_alternative<std::monostate>(*
this) and index == 0 and create) {
2354 *
this = datum::make_vector(std::monostate{});
2355 return find_one_index(index, it, it_end, create);
2362 [[nodiscard]] datum *find_one(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2367 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2368 return find_one(it + 1, it_end, create);
2370 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2371 return find_one(it + 1, it_end, create);
2373 }
else if (
hilet *indices = std::get_if<jsonpath_indices>(&*it)) {
2375 return find_one_index(indices->front(), it, it_end, create);
2377 }
else if (
hilet *names = std::get_if<jsonpath_names>(&*it)) {
2379 return find_one_name(datum{names->front()}, it, it_end,
create);