236 template<
typename To>
240 if (holds_alternative<To>(lhs) and holds_alternative<To>(rhs)) {
241 r.set(get<To>(lhs), get<To>(rhs));
243 }
else if (holds_alternative<To>(lhs) and promotable_to<To>(rhs)) {
244 r.set(get<To>(lhs),
static_cast<To
>(rhs));
246 }
else if (promotable_to<To>(lhs) and holds_alternative<To>(rhs)) {
247 r.set(
static_cast<To
>(lhs), get<To>(rhs));
253 constexpr ~datum() noexcept
258 constexpr datum(datum
const& other) noexcept : _tag(other._tag), _value(other._value)
260 if (other.is_pointer()) {
265 constexpr datum(datum&& other) noexcept : _tag(
other._tag), _value(
other._value)
267 other._tag = tag_type::monostate;
268 other._value._long_long = 0;
271 constexpr datum() noexcept : _tag(tag_type::monostate), _value(0) {}
272 constexpr explicit datum(std::monostate) noexcept : _tag(tag_type::monostate), _value(0) {}
273 constexpr explicit datum(nullptr_t) noexcept : _tag(tag_type::null), _value(0) {}
274 constexpr explicit datum(continue_type) noexcept : _tag(tag_type::flow_continue), _value(0) {}
275 constexpr explicit datum(break_type) noexcept : _tag(tag_type::flow_break), _value(0) {}
276 constexpr explicit datum(
bool value) noexcept : _tag(tag_type::boolean), _value(value) {}
277 constexpr explicit datum(std::floating_point
auto value) noexcept :
278 _tag(tag_type::floating_point), _value(narrow_cast<double>(value))
282 constexpr explicit datum(numeric_integral
auto value) noexcept :
283 _tag(tag_type::integral), _value(narrow_cast<long long>(value))
287 constexpr explicit datum(decimal value) noexcept : _tag(tag_type::decimal), _value(value) {}
288 constexpr explicit datum(std::chrono::year_month_day value) noexcept : _tag(tag_type::year_month_day), _value(value) {}
290 explicit datum(std::string_view value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
291 explicit datum(
char const *value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
292 explicit datum(vector_type value) noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
293 explicit datum(map_type value) noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
294 explicit datum(bstring value) noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
296 template<
typename... Args>
297 [[nodiscard]]
static datum
make_vector(Args
const&...args)
noexcept
299 return datum{vector_type{datum{args}...}};
302 template<
typename Key,
typename Value,
typename... Args>
303 static void populate_map(map_type& r, Key
const& key, Value
const& value, Args
const&...args)
noexcept
306 if constexpr (
sizeof...(Args) > 0) {
307 populate_map(r, args...);
311 template<
typename... Args>
312 [[nodiscard]]
static datum make_map(Args
const&...args)
noexcept
314 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
317 if constexpr (
sizeof...(Args) > 0) {
318 populate_map(r, args...);
323 [[nodiscard]]
static datum make_break() noexcept
325 return datum{break_type{}};
328 [[nodiscard]]
static datum make_continue() noexcept
330 return datum{continue_type{}};
333 constexpr datum& operator=(datum
const& other)
noexcept
335 hi_return_on_self_assignment(other);
339 _value =
other._value;
340 if (
other.is_pointer()) {
346 constexpr datum& operator=(datum&& other)
noexcept
353 constexpr datum& operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
356 _tag = tag_type::floating_point;
357 _value =
static_cast<double>(value);
361 constexpr datum& operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
364 _tag = tag_type::integral;
365 _value =
static_cast<long long>(value);
369 constexpr datum& operator=(decimal value)
372 _tag = tag_type::decimal;
376 constexpr datum& operator=(
bool value)
noexcept
379 _tag = tag_type::boolean;
384 constexpr datum& operator=(std::chrono::year_month_day value)
noexcept
387 _tag = tag_type::year_month_day;
392 constexpr datum& operator=(std::monostate)
noexcept
395 _tag = tag_type::monostate;
400 constexpr datum& operator=(nullptr_t)
noexcept
403 _tag = tag_type::null;
411 _tag = tag_type::string;
416 datum& operator=(
char const *value)
noexcept
419 _tag = tag_type::string;
424 datum& operator=(std::string_view value)
noexcept
427 _tag = tag_type::string;
432 datum& operator=(vector_type value)
noexcept
435 _tag = tag_type::vector;
436 _value =
new vector_type{
std::move(value)};
440 datum& operator=(map_type value)
noexcept
443 _tag = tag_type::map;
448 datum& operator=(bstring value)
noexcept
451 _tag = tag_type::bstring;
456 constexpr explicit operator bool() const noexcept
459 case tag_type::floating_point:
460 return to_bool(get<double>(*
this));
461 case tag_type::decimal:
462 return to_bool(get<decimal>(*
this));
463 case tag_type::boolean:
464 return get<bool>(*
this);
465 case tag_type::integral:
466 return to_bool(get<long long>(*
this));
467 case tag_type::year_month_day:
469 case tag_type::string:
470 return not get<std::string>(*this).empty();
471 case tag_type::vector:
472 return not get<vector_type>(*this).empty();
474 return not get<map_type>(*this).empty();
475 case tag_type::bstring:
476 return not get<bstring>(*this).empty();
482 [[nodiscard]]
constexpr bool empty()
const
485 case tag_type::string:
486 return get<std::string>(*this).empty();
487 case tag_type::vector:
488 return get<vector_type>(*this).empty();
490 return get<map_type>(*this).empty();
491 case tag_type::bstring:
492 return get<bstring>(*this).empty();
494 throw std::domain_error(std::format(
"Type {} can not be checked for empty", *
this));
498 template<std::
floating_po
int T>
499 constexpr explicit operator T()
const
502 case tag_type::floating_point:
503 return static_cast<T
>(get<double>(*
this));
504 case tag_type::integral:
505 return static_cast<T
>(get<long long>(*
this));
506 case tag_type::decimal:
507 return static_cast<T
>(get<decimal>(*
this));
508 case tag_type::boolean:
509 return static_cast<T
>(get<bool>(*
this));
511 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
515 constexpr explicit operator decimal()
const
518 case tag_type::floating_point:
519 return decimal(get<double>(*
this));
520 case tag_type::integral:
521 return decimal(get<long long>(*
this));
522 case tag_type::decimal:
523 return get<decimal>(*
this);
524 case tag_type::boolean:
525 return decimal(get<bool>(*
this));
527 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
531 template<numeric_
integral T>
532 constexpr explicit operator T()
const
534 if (
auto f = get_if<double>(
this)) {
535 if (not can_round_cast<T>(*f)) {
538 return round_cast<T>(*f);
540 }
else if (
auto i = get_if<long long>(
this)) {
541 if (not can_narrow_cast<T>(*i)) {
544 return narrow_cast<T>(*i);
546 }
else if (
auto d = get_if<decimal>(
this)) {
547 hilet r =
static_cast<long long>(*d);
551 return narrow_cast<T>(r);
553 }
else if (
auto b = get_if<bool>(
this)) {
554 return narrow_cast<T>(*b);
557 throw std::domain_error(std::format(
"Can't convert {} to an integral", repr(*
this)));
561 constexpr explicit operator std::chrono::year_month_day()
const
563 if (
auto ymd = get_if<std::chrono::year_month_day>(
this)) {
566 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day", repr(*
this)));
573 case tag_type::monostate:
575 case tag_type::floating_point:
577 case tag_type::decimal:
579 case tag_type::integral:
581 case tag_type::boolean:
582 return _value._bool ?
"true" :
"false";
583 case tag_type::year_month_day:
584 return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
587 case tag_type::flow_break:
589 case tag_type::flow_continue:
591 case tag_type::string:
592 return *_value._string;
593 case tag_type::vector:
596 for (
hilet& item : *_value._vector) {
606 for (
hilet& item : *_value._map) {
607 r += repr(item.first);
609 r += repr(item.second);
615 case tag_type::bstring:
616 return base64::encode(*_value._bstring);
622 explicit operator std::string_view()
const
624 if (
auto s = get_if<std::string>(
this)) {
625 return std::string_view{*s};
627 throw std::domain_error(std::format(
"Can't convert {} to an std::string_view", repr(*
this)));
631 explicit operator vector_type()
const
633 if (
auto v = get_if<vector_type>(
this)) {
636 throw std::domain_error(std::format(
"Can't convert {} to an vector", repr(*
this)));
640 explicit operator map_type()
const
642 if (
auto m = get_if<map_type>(
this)) {
649 explicit operator bstring()
const
652 if (_tag != tag_type::bstring) {
653 throw std::domain_error(std::format(
"Can't convert {} to an bstring", repr(*
this)));
655 return get<bstring>(*
this);
658 [[nodiscard]]
constexpr char const *type_name() const noexcept
661 case tag_type::floating_point:
663 case tag_type::decimal:
665 case tag_type::integral:
667 case tag_type::boolean:
669 case tag_type::year_month_day:
671 case tag_type::string:
673 case tag_type::vector:
677 case tag_type::bstring:
688 return _tag == tag_type::monostate;
694 [[nodiscard]]
constexpr bool is_break() const noexcept
696 return _tag == tag_type::flow_break;
704 return _tag == tag_type::flow_continue;
710 case tag_type::floating_point:
712 case tag_type::decimal:
714 case tag_type::integral:
716 case tag_type::boolean:
718 case tag_type::year_month_day:
721 r |= narrow_cast<uint32_t>(
static_cast<int>(_value._year_month_day.year())) << 16;
722 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.month())) << 8;
723 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.day()));
726 case tag_type::string:
728 case tag_type::vector:
731 for (
hilet& v : *_value._vector) {
732 r = hash_mix(r, v.hash());
739 for (
hilet& kv : *_value._map) {
740 r = hash_mix(r, kv.first.hash(), kv.second.hash());
744 case tag_type::bstring:
753 if (
hilet *s = get_if<std::string>(
this)) {
755 }
else if (
hilet *v = get_if<vector_type>(
this)) {
757 }
else if (
hilet *m = get_if<map_type>(
this)) {
759 }
else if (
hilet *b = get_if<bstring>(
this)) {
766 [[nodiscard]]
constexpr friend std::size_t size(datum
const& rhs)
771 [[nodiscard]]
constexpr datum
const& back()
const
773 if (
hilet *v = get_if<vector_type>(
this)) {
783 [[nodiscard]]
constexpr datum& back()
785 if (
auto *v = get_if<vector_type>(
this)) {
795 [[nodiscard]]
constexpr datum
const& front()
const
797 if (
hilet *v = get_if<vector_type>(
this)) {
803 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
807 [[nodiscard]]
constexpr datum& front()
809 if (
auto *v = get_if<vector_type>(
this)) {
815 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
819 [[nodiscard]]
constexpr auto cbegin()
const
821 if (
hilet *v = get_if<vector_type>(
this)) {
824 throw std::domain_error(std::format(
"Can not evaluate {}.cbegin()", repr(*
this)));
828 [[nodiscard]]
constexpr auto begin()
const
830 if (
hilet *v = get_if<vector_type>(
this)) {
833 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
837 [[nodiscard]]
constexpr auto begin()
839 if (
hilet *v = get_if<vector_type>(
this)) {
842 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
846 [[nodiscard]]
constexpr auto cend()
const
848 if (
hilet *v = get_if<vector_type>(
this)) {
855 [[nodiscard]]
constexpr auto end()
const
857 if (
hilet *v = get_if<vector_type>(
this)) {
864 [[nodiscard]]
constexpr auto end()
866 if (
hilet *v = get_if<vector_type>(
this)) {
877 if (
hilet *m = get_if<map_type>(
this)) {
880 for (
hilet& kv : *m) {
881 r.push_back(kv.first);
893 if (
hilet *m = get_if<map_type>(
this)) {
896 for (
hilet& kv : *m) {
897 r.push_back(kv.second);
901 throw std::domain_error(std::format(
"Can not evaluate {}.values()", repr(*
this)));
909 if (
hilet *m = get_if<map_type>(
this)) {
913 for (
hilet& item : *m) {
918 throw std::domain_error(std::format(
"Can not evaluate {}.items()", repr(*
this)));
922 constexpr void push_back(
datum const& rhs)
924 if (
auto *v = get_if<vector_type>(
this)) {
925 return v->push_back(rhs);
927 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
931 constexpr void push_back(datum&& rhs)
933 if (
auto *v = get_if<vector_type>(
this)) {
936 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
940 template<
typename Arg>
941 constexpr void push_back(Arg&& arg)
943 push_back(datum{std::forward<Arg>(arg)});
946 constexpr void pop_back()
948 if (
auto *v = get_if<vector_type>(
this)) {
952 return v->pop_back();
954 throw std::domain_error(std::format(
"Can not evaluate {}.pop_back()", repr(*
this)));
958 [[nodiscard]]
constexpr bool contains(datum
const& rhs)
const
960 if (
auto *m = get_if<map_type>(
this)) {
961 return m->contains(rhs);
963 throw std::domain_error(std::format(
"Can not evaluate {}.contains({})", repr(*
this), repr(rhs)));
967 template<
typename Arg>
968 [[nodiscard]]
constexpr bool contains(Arg
const& arg)
const
970 return contains(datum{arg});
976 find(path.cbegin(), path.cend(), r);
983 const_cast<datum *
>(
this)->
find(path.cbegin(), path.cend(), tmp);
999 return to_bool(remove(path.cbegin(), path.cend()));
1010 return find_one(path.cbegin(), path.cend(),
false);
1021 return find_one(path.cbegin(), path.cend(),
true);
1032 return const_cast<datum *
>(
this)->find_one(path.cbegin(), path.cend(),
false);
1035 [[nodiscard]]
datum const& operator[](
datum const& rhs)
const
1037 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1038 hilet& v = get<vector_type>(*
this);
1040 auto index = get<long long>(rhs);
1042 index = ssize(v) + index;
1044 if (index < 0 or index >= ssize(v)) {
1050 }
else if (holds_alternative<map_type>(*
this)) {
1051 hilet& m = get<map_type>(*
this);
1052 hilet it = m.find(rhs);
1053 if (it == m.end()) {
1060 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1064 [[nodiscard]]
constexpr datum& operator[](datum
const& rhs)
1066 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1067 auto& v = get<vector_type>(*
this);
1069 auto index = get<long long>(rhs);
1071 index = ssize(v) + index;
1073 if (index < 0 or index >= ssize(v)) {
1079 }
else if (holds_alternative<map_type>(*
this)) {
1080 auto& m = get<map_type>(*
this);
1084 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1088 [[nodiscard]]
constexpr datum
const& operator[](
auto const& rhs)
const
1090 return (*
this)[datum{rhs}];
1093 [[nodiscard]]
constexpr datum& operator[](
auto const& rhs)
1095 return (*
this)[datum{rhs}];
1098 [[nodiscard]]
constexpr datum& operator++()
1100 if (holds_alternative<long long>(*
this)) {
1101 ++_value._long_long;
1108 [[nodiscard]]
constexpr datum& operator--()
1110 if (holds_alternative<long long>(*
this)) {
1111 --_value._long_long;
1118 [[nodiscard]]
constexpr datum operator++(
int)
1120 if (holds_alternative<long long>(*
this)) {
1122 _value._long_long++;
1128 [[nodiscard]]
constexpr datum operator--(
int)
1130 if (holds_alternative<long long>(*
this)) {
1132 _value._long_long--;
1139 constexpr datum& operator+=(
auto const& rhs)
1141 if (holds_alternative<vector_type>(*
this)) {
1145 return (*
this) = (*this) + rhs;
1149#define X(op, inner_op) \
1150 constexpr datum& operator op(auto const& rhs) \
1152 return (*this) = (*this)inner_op rhs; \
1166 [[nodiscard]]
friend constexpr bool operator==(datum
const& lhs, datum
const& rhs)
noexcept
1168 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1169 return doubles.lhs() == doubles.rhs();
1171 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1172 return decimals.lhs() == decimals.rhs();
1174 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1175 return long_longs.lhs() == long_longs.rhs();
1177 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1178 return bools.lhs() == bools.rhs();
1180 }
else if (
hilet ymds = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1181 return ymds.lhs() == ymds.rhs();
1183 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1184 return strings.lhs() == strings.rhs();
1186 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1187 return vectors.lhs() == vectors.rhs();
1189 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1190 return maps.lhs() == maps.rhs();
1193 return lhs._tag == rhs._tag;
1225 [[nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const& lhs, datum
const& rhs)
noexcept
1227 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1228 return doubles.lhs() <=> doubles.rhs();
1230 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1231 return decimals.lhs() <=> decimals.rhs();
1233 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1234 return long_longs.lhs() <=> long_longs.rhs();
1236 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1237 return bools.lhs() <=> bools.rhs();
1239 }
else if (
hilet year_month_days = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1240 return year_month_days.lhs() <=> year_month_days.rhs();
1242 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1243 return strings.lhs() <=> strings.rhs();
1245 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1246 return vectors.lhs() <=> vectors.rhs();
1248 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1249 return maps.lhs() <=> maps.rhs();
1251 }
else if (
hilet bstrings = promote_if<bstring>(lhs, rhs)) {
1252 return bstrings.lhs() <=> bstrings.rhs();
1255 return lhs._tag <=> rhs._tag;
1269 [[nodiscard]]
friend constexpr datum operator-(datum
const& rhs)
1271 if (
hilet rhs_double = get_if<double>(&rhs)) {
1272 return datum{-*rhs_double};
1274 }
else if (
hilet rhs_decimal = get_if<decimal>(&rhs)) {
1275 return datum{-*rhs_decimal};
1277 }
else if (
hilet rhs_long_long = get_if<long long>(&rhs)) {
1278 return datum{-*rhs_long_long};
1294 [[nodiscard]]
friend constexpr datum operator~(datum
const& rhs)
1296 if (
hilet rhs_long_long = get_if<long long>(&rhs)) {
1297 return datum{~*rhs_long_long};
1318 [[nodiscard]]
friend constexpr datum operator+(datum
const& lhs, datum
const& rhs)
1320 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1321 return datum{doubles.lhs() + doubles.rhs()};
1323 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1324 return datum{decimals.lhs() + decimals.rhs()};
1326 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1327 return datum{long_longs.lhs() + long_longs.rhs()};
1329 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1330 return datum{strings.lhs() + strings.rhs()};
1332 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1333 auto r = vectors.lhs();
1334 r.insert(r.end(), vectors.rhs().begin(), vectors.rhs().end());
1338 throw std::domain_error(std::format(
"Can not evaluate {} '+' {}", repr(lhs), repr(rhs)));
1353 [[nodiscard]]
friend constexpr datum operator-(datum
const& lhs, datum
const& rhs)
1355 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1356 return datum{doubles.lhs() - doubles.rhs()};
1358 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1359 return datum{decimals.lhs() - decimals.rhs()};
1361 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1362 return datum{long_longs.lhs() - long_longs.rhs()};
1365 throw std::domain_error(std::format(
"Can not evaluate {} '-' {}", repr(lhs), repr(rhs)));
1380 [[nodiscard]]
friend constexpr datum operator*(datum
const& lhs, datum
const& rhs)
1382 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1383 return datum{doubles.lhs() * doubles.rhs()};
1385 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1386 return datum{decimals.lhs() * decimals.rhs()};
1388 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1389 return datum{long_longs.lhs() * long_longs.rhs()};
1392 throw std::domain_error(std::format(
"Can not evaluate {} '*' {}", repr(lhs), repr(rhs)));
1407 [[nodiscard]]
friend constexpr datum operator/(datum
const& lhs, datum
const& rhs)
1409 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1410 if (doubles.rhs() == 0) {
1411 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1413 return datum{doubles.lhs() / doubles.rhs()};
1415 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1416 if (decimals.rhs() == 0) {
1417 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1419 return datum{decimals.lhs() / decimals.rhs()};
1421 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1422 if (long_longs.rhs() == 0) {
1423 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1425 return datum{long_longs.lhs() / long_longs.rhs()};
1428 throw std::domain_error(std::format(
"Can not evaluate {} '/' {}", repr(lhs), repr(rhs)));
1443 [[nodiscard]]
friend constexpr datum operator%(datum
const& lhs, datum
const& rhs)
1445 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1446 if (long_longs.rhs() == 0) {
1447 throw std::domain_error(std::format(
"Divide by zero {} '%' {}", repr(lhs), repr(rhs)));
1449 return datum{long_longs.lhs() % long_longs.rhs()};
1452 throw std::domain_error(std::format(
"Can not evaluate {} '%' {}", repr(lhs), repr(rhs)));
1466 [[nodiscard]]
friend constexpr datum
pow(datum
const& lhs, datum
const& rhs)
1468 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1469 return datum{
pow(doubles.lhs(), doubles.rhs())};
1471 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1472 return datum{
pow(long_longs.lhs(), long_longs.rhs())};
1475 throw std::domain_error(std::format(
"Can not evaluate pow({}, {})", repr(lhs), repr(rhs)));
1489 [[nodiscard]]
friend constexpr datum operator&(datum
const& lhs, datum
const& rhs)
1491 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1492 return datum{long_longs.lhs() & long_longs.rhs()};
1494 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1495 return datum{bools.lhs() and bools.rhs()};
1498 throw std::domain_error(std::format(
"Can not evaluate {} '&' {}", repr(lhs), repr(rhs)));
1512 [[nodiscard]]
friend constexpr datum operator|(datum
const& lhs, datum
const& rhs)
1514 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1515 return datum{long_longs.lhs() | long_longs.rhs()};
1517 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1518 return datum{bools.lhs() or bools.rhs()};
1521 throw std::domain_error(std::format(
"Can not evaluate {} '|' {}", repr(lhs), repr(rhs)));
1535 [[nodiscard]]
friend constexpr datum operator^(datum
const& lhs, datum
const& rhs)
1537 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1538 return datum{long_longs.lhs() ^ long_longs.rhs()};
1540 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1541 return datum{bools.lhs() != bools.rhs()};
1544 throw std::domain_error(std::format(
"Can not evaluate {} '^' {}", repr(lhs), repr(rhs)));
1560 [[nodiscard]]
friend constexpr datum operator<<(datum
const& lhs, datum
const& rhs)
1562 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1563 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1564 throw std::domain_error(std::format(
"Invalid shift count {} '<<' {}", repr(lhs), repr(rhs)));
1566 return datum{long_longs.lhs() << long_longs.rhs()};
1569 throw std::domain_error(std::format(
"Can not evaluate {} '<<' {}", repr(lhs), repr(rhs)));
1584 [[nodiscard]]
friend constexpr datum operator>>(datum
const& lhs, datum
const& rhs)
1586 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1587 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1588 throw std::domain_error(std::format(
"Invalid shift count {} '>>' {}", repr(lhs), repr(rhs)));
1590 return datum{long_longs.lhs() >> long_longs.rhs()};
1593 throw std::domain_error(std::format(
"Can not evaluate {} '>>' {}", repr(lhs), repr(rhs)));
1603 [[nodiscard]] friend constexpr auto operator op(datum const& lhs, auto const& rhs) \
1605 return lhs op datum{rhs}; \
1607 [[nodiscard]] friend constexpr auto operator op(auto const& lhs, datum const& rhs) \
1609 return datum{lhs} op rhs; \
1626 [[nodiscard]]
friend std::string repr(datum
const& rhs)
noexcept
1629 case tag_type::monostate:
1631 case tag_type::floating_point:
1632 return std::format(
"{:.1f}", rhs._value._double);
1633 case tag_type::decimal:
1635 case tag_type::integral:
1636 return std::format(
"{}", rhs._value._long_long);
1637 case tag_type::boolean:
1638 return rhs._value._bool ?
"true" :
"false";
1639 case tag_type::year_month_day:
1640 return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1641 case tag_type::null:
1643 case tag_type::flow_break:
1645 case tag_type::flow_continue:
1647 case tag_type::string:
1648 return std::format(
"\"{}\"", *rhs._value._string);
1649 case tag_type::vector:
1652 for (
hilet& item : *rhs._value._vector) {
1662 for (
hilet& item : *rhs._value._map) {
1663 r += repr(item.first);
1665 r += repr(item.second);
1671 case tag_type::bstring:
1672 return base64::encode(*rhs._value._bstring);
1691 template<
typename T>
1694 if constexpr (std::is_same_v<T, double>) {
1695 return rhs._tag == tag_type::floating_point;
1696 }
else if constexpr (std::is_same_v<T, decimal>) {
1697 return rhs._tag == tag_type::decimal;
1698 }
else if constexpr (std::is_same_v<T, long long>) {
1699 return rhs._tag == tag_type::integral;
1700 }
else if constexpr (std::is_same_v<T, bool>) {
1701 return rhs._tag == tag_type::boolean;
1702 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1703 return rhs._tag == tag_type::year_month_day;
1704 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1705 return rhs._tag == tag_type::null;
1706 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1707 return rhs._tag == tag_type::monostate;
1708 }
else if constexpr (std::is_same_v<T, break_type>) {
1709 return rhs._tag == tag_type::flow_break;
1710 }
else if constexpr (std::is_same_v<T, continue_type>) {
1711 return rhs._tag == tag_type::flow_continue;
1712 }
else if constexpr (std::is_same_v<T, std::string>) {
1713 return rhs._tag == tag_type::string;
1714 }
else if constexpr (std::is_same_v<T, vector_type>) {
1715 return rhs._tag == tag_type::vector;
1716 }
else if constexpr (std::is_same_v<T, map_type>) {
1717 return rhs._tag == tag_type::map;
1718 }
else if constexpr (std::is_same_v<T, bstring>) {
1719 return rhs._tag == tag_type::bstring;
1736 template<
typename To>
1739 if constexpr (std::is_same_v<To, double>) {
1740 return holds_alternative<double>(rhs) or holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or
1741 holds_alternative<bool>(rhs);
1742 }
else if constexpr (std::is_same_v<To, decimal>) {
1743 return holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1744 }
else if constexpr (std::is_same_v<To, long long>) {
1745 return holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1747 return holds_alternative<To>(rhs);
1759 template<
typename T>
1760 [[nodiscard]]
friend constexpr T
const&
get(
datum const& rhs)
noexcept
1762 hi_axiom(holds_alternative<T>(rhs));
1763 if constexpr (std::is_same_v<T, double>) {
1764 return rhs._value._double;
1765 }
else if constexpr (std::is_same_v<T, decimal>) {
1766 return rhs._value._decimal;
1767 }
else if constexpr (std::is_same_v<T, long long>) {
1768 return rhs._value._long_long;
1769 }
else if constexpr (std::is_same_v<T, bool>) {
1770 return rhs._value._bool;
1771 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1772 return rhs._value._year_month_day;
1773 }
else if constexpr (std::is_same_v<T, std::string>) {
1774 return *rhs._value._string;
1775 }
else if constexpr (std::is_same_v<T, vector_type>) {
1776 return *rhs._value._vector;
1777 }
else if constexpr (std::is_same_v<T, map_type>) {
1778 return *rhs._value._map;
1779 }
else if constexpr (std::is_same_v<T, bstring>) {
1780 return *rhs._value._bstring;
1794 template<
typename T>
1795 [[nodiscard]]
friend constexpr T&
get(
datum& rhs)
noexcept
1797 hi_axiom(holds_alternative<T>(rhs));
1798 if constexpr (std::is_same_v<T, double>) {
1799 return rhs._value._double;
1800 }
else if constexpr (std::is_same_v<T, decimal>) {
1801 return rhs._value._decimal;
1802 }
else if constexpr (std::is_same_v<T, long long>) {
1803 return rhs._value._long_long;
1804 }
else if constexpr (std::is_same_v<T, bool>) {
1805 return rhs._value._bool;
1806 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1807 return rhs._value._year_month_day;
1808 }
else if constexpr (std::is_same_v<T, std::string>) {
1809 return *rhs._value._string;
1810 }
else if constexpr (std::is_same_v<T, vector_type>) {
1811 return *rhs._value._vector;
1812 }
else if constexpr (std::is_same_v<T, map_type>) {
1813 return *rhs._value._map;
1814 }
else if constexpr (std::is_same_v<T, bstring>) {
1815 return *rhs._value._bstring;
1829 template<
typename T>
1830 [[deprecated]] [[nodiscard]]
friend constexpr T *
get_if(
datum& rhs)
noexcept
1832 if (holds_alternative<T>(rhs)) {
1833 return &get<T>(rhs);
1847 template<
typename T>
1848 [[deprecated]] [[nodiscard]]
friend constexpr T
const *
get_if(
datum const& rhs)
noexcept
1850 if (holds_alternative<T>(rhs)) {
1851 return &get<T>(rhs);
1865 template<
typename T>
1868 if (rhs ==
nullptr or not holds_alternative<T>(*rhs)) {
1871 return &get<T>(*rhs);
1882 template<
typename T>
1883 [[nodiscard]]
friend constexpr T
const *
get_if(
datum const *rhs)
noexcept
1885 if (rhs ==
nullptr or not holds_alternative<T>(*rhs)) {
1888 return &get<T>(*rhs);
1900 template<
typename T>
1903 if (
auto *value = rhs.find_one(path)) {
1904 if (holds_alternative<T>(*value)) {
1905 return &get<T>(*value);
1923 template<
typename T>
1926 if (
auto *value =
const_cast<datum&
>(rhs).find_one(path)) {
1927 if (holds_alternative<T>(*value)) {
1928 return &get<T>(*value);
1938 enum class tag_type :
signed char {
1957 tag_type _tag = tag_type::monostate;
1960 long long _long_long;
1963 std::chrono::year_month_day _year_month_day;
1965 vector_type *_vector;
1969 constexpr value_type(numeric_integral
auto value) noexcept : _long_long(narrow_cast<long long>(value)) {}
1970 constexpr value_type(std::floating_point
auto value) noexcept : _double(narrow_cast<double>(value)) {}
1971 constexpr value_type(decimal value) noexcept : _decimal(value) {}
1972 constexpr value_type(
bool value) noexcept : _bool(value) {}
1973 constexpr value_type(std::chrono::year_month_day value) noexcept : _year_month_day(value) {}
1974 constexpr value_type(
std::string *value) noexcept : _string(value) {}
1975 constexpr value_type(vector_type *value) noexcept : _vector(value) {}
1976 constexpr value_type(map_type *value) noexcept : _map(value) {}
1977 constexpr value_type(bstring *value) noexcept : _bstring(value) {}
1982 [[nodiscard]]
constexpr bool is_scalar() const noexcept
1984 return to_underlying(_tag) >= 0;
1987 [[nodiscard]]
constexpr bool is_pointer() const noexcept
1989 return to_underlying(_tag) < 0;
1992 hi_no_inline
void copy_pointer(datum
const& other)
noexcept
1995 switch (
other._tag) {
1996 case tag_type::string:
1999 case tag_type::vector:
2000 _value._vector =
new vector_type{*
other._value._vector};
2003 _value._map =
new map_type{*
other._value._map};
2005 case tag_type::bstring:
2006 _value._bstring =
new bstring{*
other._value._bstring};
2013 hi_no_inline
void _delete_pointer() noexcept
2017 case tag_type::string:
2018 delete _value._string;
2020 case tag_type::vector:
2021 delete _value._vector;
2026 case tag_type::bstring:
2027 delete _value._bstring;
2034 constexpr void delete_pointer() noexcept
2041 void find_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2043 if (
auto vector = get_if<datum::vector_type>(
this)) {
2044 for (
auto& item : *vector) {
2045 item.find(it + 1, it_end, r);
2048 }
else if (
auto map = get_if<datum::map_type>(
this)) {
2049 for (
auto& item : *map) {
2050 item.second.find(it + 1, it_end, r);
2055 void find_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2057 this->
find(it + 1, it_end, r);
2059 if (
auto vector = get_if<datum::vector_type>(
this)) {
2060 for (
auto& item : *vector) {
2061 item.find(it, it_end, r);
2064 }
else if (
auto map = get_if<datum::map_type>(
this)) {
2065 for (
auto& item : *map) {
2066 item.second.find(it, it_end, r);
2072 jsonpath_indices
const& indices,
2073 jsonpath::const_iterator it,
2074 jsonpath::const_iterator it_end,
2077 if (
auto vector = get_if<datum::vector_type>(
this)) {
2078 for (
hilet index : indices.filter(ssize(*vector))) {
2079 (*vector)[index].find(it + 1, it_end, r);
2085 jsonpath_names
const& names,
2086 jsonpath::const_iterator it,
2087 jsonpath::const_iterator it_end,
2090 if (
auto map = get_if<datum::map_type>(
this)) {
2091 for (
hilet& name : names) {
2092 hilet name_ = datum{name};
2093 auto jt = map->find(name_);
2094 if (jt != map->cend()) {
2095 jt->second.find(it + 1, it_end, r);
2102 jsonpath_slice
const& slice,
2103 jsonpath::const_iterator it,
2104 jsonpath::const_iterator it_end,
2107 if (
auto vector = get_if<datum::vector_type>(
this)) {
2108 hilet first = slice.begin(vector->size());
2109 hilet last = slice.end(vector->size());
2111 for (
auto index = first; index != last; index += slice.step) {
2112 if (index >= 0 and index < vector->size()) {
2113 (*this)[index].find(it + 1, it_end, r);
2124 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2125 find(it + 1, it_end, r);
2127 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2128 find(it + 1, it_end, r);
2130 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2131 find_wildcard(it, it_end, r);
2133 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2134 find_descend(it, it_end, r);
2136 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2137 find_indices(*indices, it, it_end, r);
2139 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2140 find_names(*names, it, it_end, r);
2142 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2143 find_slice(*slice, it, it_end, r);
2150 [[nodiscard]]
int remove_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2154 if (
auto vector = get_if<datum::vector_type>(
this)) {
2155 auto jt = vector->begin();
2156 while (jt != vector->end()) {
2157 hilet match = jt->remove(it + 1, it_end);
2161 jt = vector->erase(jt);
2166 return vector->empty() ? 2 : r;
2168 }
else if (
auto map = get_if<datum::map_type>(
this)) {
2169 auto jt = map->begin();
2170 while (jt != map->end()) {
2171 hilet match = jt->second.remove(it + 1, it_end);
2175 jt = map->erase(jt);
2180 return map->empty() ? 2 : r;
2187 [[nodiscard]]
int remove_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2199 if (
auto vector = get_if<datum::vector_type>(
this)) {
2200 auto jt = vector->begin();
2201 while (jt != vector->end()) {
2202 hilet match = jt->remove(it, it_end);
2206 jt = vector->erase(jt);
2211 return vector->empty() ? 2 : r;
2213 }
else if (
auto map = get_if<datum::map_type>(
this)) {
2214 auto jt = map->begin();
2215 while (jt != map->end()) {
2216 hilet match = jt->second.remove(it, it_end);
2220 jt = map->erase(jt);
2225 return map->empty() ? 2 : r;
2233 remove_indices(jsonpath_indices
const& indices, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2235 if (
auto vector = get_if<datum::vector_type>(
this)) {
2239 for (
hilet index : indices.filter(ssize(*vector))) {
2240 hilet match = (*vector)[index - offset].remove(it + 1, it_end);
2243 vector->erase(vector->begin() + (index - offset));
2248 return vector->empty() ? 2 : r;
2256 remove_names(jsonpath_names
const& names, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2258 if (
auto map = get_if<datum::map_type>(
this)) {
2261 for (
hilet& name : names) {
2262 hilet name_ = datum{name};
2263 auto jt = map->find(name_);
2264 if (jt != map->cend()) {
2265 hilet match = jt->second.remove(it + 1, it_end);
2273 return map->empty() ? 2 : r;
2281 remove_slice(jsonpath_slice
const& slice, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2283 if (
auto vector = get_if<datum::vector_type>(
this)) {
2286 hilet first = slice.begin(vector->size());
2287 hilet last = slice.end(vector->size());
2290 for (
auto index = first; index != last; index += slice.step) {
2291 if (index >= 0 and index < vector->size()) {
2292 hilet match = (*this)[index - offset].remove(it + 1, it_end);
2296 vector->erase(vector->begin() + (index - offset));
2302 return vector->empty() ? 2 : r;
2309 [[nodiscard]]
int remove(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2315 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2316 return remove(it + 1, it_end);
2318 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2319 return remove(it + 1, it_end);
2321 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2322 return remove_wildcard(it, it_end);
2324 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2325 return remove_descend(it, it_end);
2327 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2328 return remove_indices(*indices, it, it_end);
2330 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2331 return remove_names(*names, it, it_end);
2333 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2334 return remove_slice(*slice, it, it_end);
2341 [[nodiscard]] datum *
2342 find_one_name(datum
const& name, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2344 hi_axiom(holds_alternative<std::string>(name));
2346 if (
auto *map = get_if<map_type>(
this)) {
2347 auto i = map->find(name);
2348 if (i != map->end()) {
2349 return i->second.find_one(it + 1, it_end, create);
2351 }
else if (create) {
2352 (*map)[name] = datum{std::monostate{}};
2353 return find_one_name(name, it, it_end, create);
2359 }
else if (holds_alternative<std::monostate>(*
this) and create) {
2360 *
this = datum::make_map(name, std::monostate{});
2361 return find_one_name(name, it, it_end, create);
2368 [[nodiscard]] datum *
2369 find_one_index(
std::size_t index, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2371 if (
auto *vector = get_if<vector_type>(
this)) {
2372 if (index < vector->size()) {
2373 return (*vector)[index].find_one(it + 1, it_end, create);
2374 }
else if (index == vector->size() and create) {
2375 vector->push_back(datum{std::monostate{}});
2376 return find_one_index(index, it, it_end, create);
2381 }
else if (holds_alternative<std::monostate>(*
this) and index == 0 and create) {
2382 *
this = datum::make_vector(std::monostate{});
2383 return find_one_index(index, it, it_end, create);
2390 [[nodiscard]] datum *find_one(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2395 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2396 return find_one(it + 1, it_end, create);
2398 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2399 return find_one(it + 1, it_end, create);
2401 }
else if (
hilet *indices = std::get_if<jsonpath_indices>(&*it)) {
2403 return find_one_index(indices->front(), it, it_end, create);
2405 }
else if (
hilet *names = std::get_if<jsonpath_names>(&*it)) {
2407 return find_one_name(datum{names->front()}, it, it_end,
create);