222 constexpr ~datum() noexcept
227 constexpr datum(
datum const &other) noexcept : _tag(other._tag), _value(other._value)
229 if (other.is_pointer()) {
234 constexpr datum(datum &&other) noexcept : _tag(other._tag), _value(other._value)
236 other._tag = tag_type::monostate;
237 other._value._long_long = 0;
240 constexpr datum() noexcept : _tag(tag_type::monostate), _value(0) {}
241 constexpr explicit datum(std::monostate) noexcept : _tag(tag_type::monostate), _value(0) {}
242 constexpr explicit datum(nullptr_t) noexcept : _tag(tag_type::null), _value(0) {}
243 constexpr explicit datum(continue_type) noexcept : _tag(tag_type::flow_continue), _value(0) {}
244 constexpr explicit datum(break_type) noexcept : _tag(tag_type::flow_break), _value(0) {}
245 constexpr explicit datum(
bool value) noexcept : _tag(tag_type::boolean), _value(value) {}
246 constexpr explicit datum(std::floating_point
auto value) noexcept :
247 _tag(tag_type::floating_point), _value(
static_cast<double>(value))
251 constexpr explicit datum(numeric_integral
auto value) noexcept :
252 _tag(tag_type::integral), _value(
static_cast<long long>(value))
256 constexpr explicit datum(decimal value) noexcept : _tag(tag_type::decimal), _value(value) {}
257 constexpr explicit datum(std::chrono::year_month_day value) noexcept : _tag(tag_type::year_month_day), _value(value) {}
259 explicit datum(std::string_view value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
260 explicit datum(
char const *value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
261 explicit datum(vector_type value) noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
262 explicit datum(map_type value) noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
263 explicit datum(URL value) noexcept : _tag(tag_type::url), _value(
new URL{
std::move(value)}) {}
264 explicit datum(bstring value) noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
266 template<
typename... Args>
267 [[nodiscard]]
static datum make_vector(Args
const &...args)
noexcept
269 return datum{vector_type{datum{args}...}};
272 template<
typename Key,
typename Value,
typename... Args>
273 [[nodiscard]]
static void populate_map(map_type &r, Key
const &key, Value
const &value, Args
const &...args)
noexcept
276 if constexpr (
sizeof...(Args) > 0) {
277 populate_map(r, args...);
281 template<
typename... Args>
282 [[nodiscard]]
static datum make_map(Args
const &...args)
noexcept
284 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
287 if constexpr (
sizeof...(Args) > 0) {
288 populate_map(r, args...);
293 [[nodiscard]]
static datum make_break() noexcept
295 return datum{break_type{}};
298 [[nodiscard]]
static datum make_continue() noexcept
300 return datum{continue_type{}};
303 constexpr datum &operator=(datum
const &other)
noexcept
305 tt_return_on_self_assignment(other);
309 _value = other._value;
310 if (other.is_pointer()) {
316 constexpr datum &operator=(datum &&other)
noexcept
323 constexpr datum &operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
326 _tag = tag_type::floating_point;
327 _value =
static_cast<double>(value);
331 constexpr datum &operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
334 _tag = tag_type::integral;
335 _value =
static_cast<long long>(value);
339 constexpr datum &operator=(decimal value)
342 _tag = tag_type::decimal;
346 constexpr datum &operator=(
bool value)
noexcept
349 _tag = tag_type::boolean;
354 constexpr datum &operator=(std::chrono::year_month_day value)
noexcept
357 _tag = tag_type::year_month_day;
362 constexpr datum &operator=(std::monostate)
noexcept
365 _tag = tag_type::monostate;
370 constexpr datum &operator=(nullptr_t)
noexcept
373 _tag = tag_type::null;
381 _tag = tag_type::string;
386 datum &operator=(
char const *value)
noexcept
389 _tag = tag_type::string;
394 datum &operator=(std::string_view value)
noexcept
397 _tag = tag_type::string;
402 datum &operator=(vector_type value)
noexcept
405 _tag = tag_type::vector;
406 _value =
new vector_type{
std::move(value)};
410 datum &operator=(map_type value)
noexcept
413 _tag = tag_type::map;
418 datum &operator=(URL value)
noexcept
421 _tag = tag_type::url;
426 datum &operator=(bstring value)
noexcept
429 _tag = tag_type::bstring;
434 constexpr explicit operator bool() const noexcept
437 case tag_type::floating_point:
return static_cast<bool>(get<double>(*
this));
438 case tag_type::decimal:
return static_cast<bool>(get<decimal>(*
this));
439 case tag_type::boolean:
return get<bool>(*
this);
440 case tag_type::integral:
return static_cast<bool>(get<long long>(*
this));
441 case tag_type::year_month_day:
return true;
442 case tag_type::string:
return static_cast<bool>(std::size(get<std::string>(*
this)));
443 case tag_type::vector:
return static_cast<bool>(std::size(get<vector_type>(*
this)));
444 case tag_type::map:
return static_cast<bool>(std::size(get<map_type>(*
this)));
445 case tag_type::url:
return static_cast<bool>(get<URL>(*
this));
446 case tag_type::bstring:
return static_cast<bool>(std::size(get<bstring>(*
this)));
447 default:
return false;
451 template<std::
floating_po
int T>
452 constexpr explicit operator T()
const
455 case tag_type::floating_point:
return static_cast<T
>(get<double>(*
this));
456 case tag_type::integral:
return static_cast<T
>(get<long long>(*
this));
457 case tag_type::decimal:
return static_cast<T
>(get<decimal>(*
this));
458 case tag_type::boolean:
return static_cast<T
>(get<bool>(*
this));
459 default:
throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
463 constexpr explicit operator decimal()
const
466 case tag_type::floating_point:
return decimal(get<double>(*
this));
467 case tag_type::integral:
return decimal(get<long long>(*
this));
468 case tag_type::decimal:
return get<decimal>(*
this);
469 case tag_type::boolean:
return decimal(get<bool>(*
this));
470 default:
throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
474 template<numeric_
integral T>
475 constexpr explicit operator T()
const
477 if (
auto f = get_if<double>(*
this)) {
483 return static_cast<T
>(r);
485 }
else if (
auto i = get_if<long long>(*
this)) {
489 return static_cast<T
>(*i);
491 }
else if (
auto d = get_if<decimal>(*
this)) {
492 auto r =
static_cast<long long>(*d);
496 return static_cast<T
>(r);
498 }
else if (
auto b = get_if<bool>(*
this)) {
499 return static_cast<T
>(*b);
502 throw std::domain_error(std::format(
"Can't convert {} to an integral", repr(*
this)));
506 constexpr explicit operator std::chrono::year_month_day()
const
508 if (
auto ymd = get_if<std::chrono::year_month_day>(*
this)) {
511 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day", repr(*
this)));
518 case tag_type::monostate:
return "undefined";
519 case tag_type::floating_point:
return tt::to_string(_value._double);
520 case tag_type::decimal:
return to_string(_value._decimal);
521 case tag_type::integral:
return to_string(_value._long_long);
522 case tag_type::boolean:
return _value._bool ?
"true" :
"false";
523 case tag_type::year_month_day:
return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
524 case tag_type::null:
return "null";
525 case tag_type::flow_break:
return "break";
526 case tag_type::flow_continue:
return "continue";
527 case tag_type::string:
return *_value._string;
528 case tag_type::url:
return to_string(*_value._url);
529 case tag_type::vector: {
531 for (ttlet &item : *_value._vector) {
538 case tag_type::map: {
540 for (ttlet &item : *_value._map) {
541 r += repr(item.first);
543 r += repr(item.second);
550 default: tt_no_default();
554 explicit operator std::string_view()
const
556 if (
auto s = get_if<std::string>(*
this)) {
557 return std::string_view{*s};
558 }
else if (
auto u = get_if<URL>(*
this)) {
561 throw std::domain_error(std::format(
"Can't convert {} to an std::string_view", repr(*
this)));
565 explicit operator vector_type()
const
567 if (
auto v = get_if<vector_type>(*
this)) {
570 throw std::domain_error(std::format(
"Can't convert {} to an vector", repr(*
this)));
574 explicit operator map_type()
const
576 if (
auto m = get_if<map_type>(*
this)) {
583 explicit operator URL()
const
585 if (
auto u = get_if<URL>(*
this)) {
587 }
else if (
auto s = get_if<std::string>(*
this)) {
594 explicit operator bstring()
const
597 if (_tag != tag_type::bstring) {
598 throw std::domain_error(std::format(
"Can't convert {} to an bstring", repr(*
this)));
600 return get<bstring>(*
this);
603 [[nodiscard]]
constexpr char const *type_name() const noexcept
606 case tag_type::floating_point:
return "float";
607 case tag_type::decimal:
return "decimal";
608 case tag_type::integral:
return "int";
609 case tag_type::boolean:
return "bool";
610 case tag_type::year_month_day:
return "date";
611 case tag_type::string:
return "string";
612 case tag_type::url:
return "url";
613 case tag_type::vector:
return "vector";
614 case tag_type::map:
return "map";
615 case tag_type::bstring:
return "bytes";
616 default: tt_no_default();
624 return _tag == tag_type::monostate;
630 [[nodiscard]]
constexpr bool is_break() const noexcept
632 return _tag == tag_type::flow_break;
640 return _tag == tag_type::flow_continue;
643 [[nodiscard]]
constexpr size_t hash() const noexcept
650 case tag_type::year_month_day: {
652 r |=
static_cast<uint32_t
>(
static_cast<int>(_value._year_month_day.year())) << 16;
653 r |=
static_cast<uint32_t
>(
static_cast<unsigned>(_value._year_month_day.month())) << 8;
654 r |=
static_cast<uint32_t
>(
static_cast<unsigned>(_value._year_month_day.day()));
658 case tag_type::vector: {
660 for (ttlet &v : *_value._vector) {
661 r = hash_mix(r, v.hash());
665 case tag_type::map: {
667 for (ttlet &kv : *_value._map) {
668 r = hash_mix(r, kv.first.hash(), kv.second.hash());
674 default: tt_no_default();
678 [[nodiscard]]
constexpr size_t size()
const
680 if (ttlet *s = get_if<std::string>(*
this)) {
681 return std::size(*s);
682 }
else if (ttlet *v = get_if<vector_type>(*
this)) {
683 return std::size(*v);
684 }
else if (ttlet *m = get_if<map_type>(*
this)) {
685 return std::size(*m);
686 }
else if (ttlet *b = get_if<bstring>(*
this)) {
687 return std::size(get<bstring>(*
this));
693 [[nodiscard]]
constexpr datum
const &back()
const
695 if (ttlet *v = get_if<vector_type>(*
this)) {
705 [[nodiscard]]
constexpr datum &back()
707 if (
auto *v = get_if<vector_type>(*
this)) {
717 [[nodiscard]]
constexpr datum
const &front()
const
719 if (ttlet *v = get_if<vector_type>(*
this)) {
725 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
729 [[nodiscard]]
constexpr datum &front()
731 if (
auto *v = get_if<vector_type>(*
this)) {
737 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
741 [[nodiscard]]
constexpr auto cbegin()
const
743 if (ttlet *v = get_if<vector_type>(*
this)) {
746 throw std::domain_error(std::format(
"Can not evaluate {}.cbegin()", repr(*
this)));
750 [[nodiscard]]
constexpr auto begin()
const
752 if (ttlet *v = get_if<vector_type>(*
this)) {
755 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
759 [[nodiscard]]
constexpr auto begin()
761 if (ttlet *v = get_if<vector_type>(*
this)) {
764 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
768 [[nodiscard]]
constexpr auto cend()
const
770 if (ttlet *v = get_if<vector_type>(*
this)) {
777 [[nodiscard]]
constexpr auto end()
const
779 if (ttlet *v = get_if<vector_type>(*
this)) {
786 [[nodiscard]]
constexpr auto end()
788 if (ttlet *v = get_if<vector_type>(*
this)) {
799 if (ttlet *m = get_if<map_type>(*
this)) {
802 for (ttlet &kv : *m) {
803 r.push_back(kv.first);
815 if (ttlet *m = get_if<map_type>(*
this)) {
818 for (ttlet &kv : *m) {
819 r.push_back(kv.second);
823 throw std::domain_error(std::format(
"Can not evaluate {}.values()", repr(*
this)));
831 if (ttlet *m = get_if<map_type>(*
this)) {
835 for (ttlet &item : *m) {
836 r.push_back(make_vector(item.first, item.second));
840 throw std::domain_error(std::format(
"Can not evaluate {}.items()", repr(*
this)));
844 constexpr void push_back(
datum const &rhs)
846 if (
auto *v = get_if<vector_type>(*
this)) {
847 return v->push_back(rhs);
849 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
853 constexpr void push_back(datum &&rhs)
855 if (
auto *v = get_if<vector_type>(*
this)) {
858 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
862 template<
typename Arg>
863 constexpr void push_back(Arg &&arg)
865 push_back(datum{std::forward<Arg>(arg)});
868 constexpr void pop_back()
870 if (
auto *v = get_if<vector_type>(*
this)) {
874 return v->pop_back();
876 throw std::domain_error(std::format(
"Can not evaluate {}.pop_back()", repr(*
this)));
880 [[nodiscard]]
constexpr bool contains(datum
const &rhs)
const
882 if (
auto *m = get_if<map_type>(*
this)) {
883 return m->contains(rhs);
885 throw std::domain_error(std::format(
"Can not evaluate {}.contains({})", repr(*
this), repr(rhs)));
889 template<
typename Arg>
890 [[nodiscard]]
constexpr bool contains(Arg
const &arg)
const
892 return contains(datum{arg});
898 find(std::cbegin(path), std::cend(path), r);
905 const_cast<datum *
>(
this)->find(std::cbegin(path), std::cend(path), tmp);
921 return static_cast<bool>(
remove(std::cbegin(path), std::cend(path)));
931 tt_axiom(path.is_singular());
932 return find_one(std::cbegin(path), std::cend(path),
false);
942 tt_axiom(path.is_singular());
943 return find_one(std::cbegin(path), std::cend(path),
true);
953 tt_axiom(path.is_singular());
954 return const_cast<datum *
>(
this)->
find_one(std::cbegin(path), std::cend(path),
false);
957 [[nodiscard]]
constexpr datum const &operator[](
datum const &rhs)
const
959 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
960 ttlet &v = get<vector_type>(*
this);
962 auto index = get<long long>(rhs);
964 index = std::ssize(v) + index;
966 if (index < 0 or index >= std::ssize(v)) {
972 }
else if (holds_alternative<map_type>(*
this)) {
973 ttlet &m = get<map_type>(*
this);
974 ttlet it = m.find(rhs);
982 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
986 [[nodiscard]]
constexpr datum &operator[](datum
const &rhs)
988 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
989 auto &v = get<vector_type>(*
this);
991 auto index = get<long long>(rhs);
993 index = std::ssize(v) + index;
995 if (index < 0 or index >= std::ssize(v)) {
1001 }
else if (holds_alternative<map_type>(*
this)) {
1002 auto &m = get<map_type>(*
this);
1006 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1010 [[nodiscard]]
constexpr datum
const &operator[](
auto const &rhs)
const
1012 return (*
this)[datum{rhs}];
1015 [[nodiscard]]
constexpr datum &operator[](
auto const &rhs)
1017 return (*
this)[datum{rhs}];
1020 [[nodiscard]]
constexpr datum &operator++()
1022 if (holds_alternative<long long>(*
this)) {
1023 ++_value._long_long;
1030 [[nodiscard]]
constexpr datum &operator--()
1032 if (holds_alternative<long long>(*
this)) {
1033 --_value._long_long;
1040 [[nodiscard]]
constexpr datum operator++(
int)
1042 if (holds_alternative<long long>(*
this)) {
1044 _value._long_long++;
1050 [[nodiscard]]
constexpr datum operator--(
int)
1052 if (holds_alternative<long long>(*
this)) {
1054 _value._long_long--;
1061 constexpr datum &operator+=(
auto const &rhs)
1063 if (holds_alternative<vector_type>(*
this)) {
1067 return (*
this) = (*this) + rhs;
1071#define X(op, inner_op) \
1072 constexpr datum &operator op(auto const &rhs) \
1074 return (*this) = (*this)inner_op rhs; \
1088 [[nodiscard]]
friend constexpr bool operator==(datum
const &lhs, datum
const &rhs)
noexcept
1090 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1091 return doubles.lhs() == doubles.rhs();
1093 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1094 return decimals.lhs() == decimals.rhs();
1096 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1097 return long_longs.lhs() == long_longs.rhs();
1099 }
else if (ttlet bools = promote_if<bool>(lhs, rhs)) {
1100 return bools.lhs() == bools.rhs();
1102 }
else if (ttlet ymds = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1103 return ymds.lhs() == ymds.rhs();
1105 }
else if (ttlet urls = promote_if<URL>(lhs, rhs)) {
1106 return urls.lhs() == urls.rhs();
1108 }
else if (ttlet strings = promote_if<std::string>(lhs, rhs)) {
1109 return strings.lhs() == strings.rhs();
1111 }
else if (ttlet vectors = promote_if<vector_type>(lhs, rhs)) {
1112 return vectors.lhs() == vectors.rhs();
1114 }
else if (ttlet maps = promote_if<map_type>(lhs, rhs)) {
1115 return maps.lhs() == maps.rhs();
1118 return lhs._tag == rhs._tag;
1152 [[nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const &lhs, datum
const &rhs)
noexcept
1154 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1155 return doubles.lhs() <=> doubles.rhs();
1157 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1158 return decimals.lhs() <=> decimals.rhs();
1160 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1161 return long_longs.lhs() <=> long_longs.rhs();
1163 }
else if (ttlet bools = promote_if<bool>(lhs, rhs)) {
1164 return bools.lhs() <=> bools.rhs();
1166 }
else if (ttlet year_month_days = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1167 return year_month_days.lhs() <=> year_month_days.rhs();
1169 }
else if (ttlet urls = promote_if<URL>(lhs, rhs)) {
1170 return urls.lhs() <=> urls.rhs();
1172 }
else if (ttlet strings = promote_if<std::string>(lhs, rhs)) {
1173 return strings.lhs() <=> strings.rhs();
1175 }
else if (ttlet vectors = promote_if<vector_type>(lhs, rhs)) {
1176 return vectors.lhs() <=> vectors.rhs();
1178 }
else if (ttlet maps = promote_if<map_type>(lhs, rhs)) {
1179 return maps.lhs() <=> maps.rhs();
1181 }
else if (ttlet bstrings = promote_if<bstring>(lhs, rhs)) {
1182 return bstrings.lhs() <=> bstrings.rhs();
1185 return lhs._tag <=> rhs._tag;
1199 [[nodiscard]]
friend constexpr datum operator-(datum
const &rhs)
1201 if (ttlet rhs_double = get_if<double>(rhs)) {
1202 return datum{-*rhs_double};
1204 }
else if (ttlet rhs_decimal = get_if<decimal>(rhs)) {
1205 return datum{-*rhs_decimal};
1207 }
else if (ttlet rhs_long_long = get_if<long long>(rhs)) {
1208 return datum{-*rhs_long_long};
1224 [[nodiscard]]
friend constexpr datum operator~(datum
const &rhs)
1226 if (ttlet rhs_long_long = get_if<long long>(rhs)) {
1227 return datum{~*rhs_long_long};
1248 [[nodiscard]]
friend constexpr datum operator+(datum
const &lhs, datum
const &rhs)
1250 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1251 return datum{doubles.lhs() + doubles.rhs()};
1253 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1254 return datum{decimals.lhs() + decimals.rhs()};
1256 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1257 return datum{long_longs.lhs() + long_longs.rhs()};
1259 }
else if (ttlet strings = promote_if<std::string>(lhs, rhs)) {
1260 return datum{strings.lhs() + strings.rhs()};
1262 }
else if (ttlet vectors = promote_if<vector_type>(lhs, rhs)) {
1263 auto r = vectors.lhs();
1264 r.insert(r.end(), vectors.rhs().begin(), vectors.rhs().end());
1268 throw std::domain_error(std::format(
"Can not evaluate {} '+' {}", repr(lhs), repr(rhs)));
1283 [[nodiscard]]
friend constexpr datum operator-(datum
const &lhs, datum
const &rhs)
1285 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1286 return datum{doubles.lhs() - doubles.rhs()};
1288 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1289 return datum{decimals.lhs() - decimals.rhs()};
1291 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1292 return datum{long_longs.lhs() - long_longs.rhs()};
1295 throw std::domain_error(std::format(
"Can not evaluate {} '-' {}", repr(lhs), repr(rhs)));
1310 [[nodiscard]]
friend constexpr datum operator*(datum
const &lhs, datum
const &rhs)
1312 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1313 return datum{doubles.lhs() * doubles.rhs()};
1315 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1316 return datum{decimals.lhs() * decimals.rhs()};
1318 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1319 return datum{long_longs.lhs() * long_longs.rhs()};
1322 throw std::domain_error(std::format(
"Can not evaluate {} '*' {}", repr(lhs), repr(rhs)));
1339 [[nodiscard]]
friend constexpr datum operator/(datum
const &lhs, datum
const &rhs)
1341 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1342 if (doubles.rhs() == 0) {
1343 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1345 return datum{doubles.lhs() / doubles.rhs()};
1347 }
else if (ttlet decimals = promote_if<decimal>(lhs, rhs)) {
1348 if (decimals.rhs() == 0) {
1349 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1351 return datum{decimals.lhs() / decimals.rhs()};
1353 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1354 if (long_longs.rhs() == 0) {
1355 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1357 return datum{long_longs.lhs() / long_longs.rhs()};
1359 }
else if (ttlet urls = promote_if<URL>(lhs, rhs)) {
1360 return datum{urls.lhs() / urls.rhs()};
1363 throw std::domain_error(std::format(
"Can not evaluate {} '/' {}", repr(lhs), repr(rhs)));
1378 [[nodiscard]]
friend constexpr datum operator%(datum
const &lhs, datum
const &rhs)
1380 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1381 if (long_longs.rhs() == 0) {
1382 throw std::domain_error(std::format(
"Divide by zero {} '%' {}", repr(lhs), repr(rhs)));
1384 return datum{long_longs.lhs() % long_longs.rhs()};
1387 throw std::domain_error(std::format(
"Can not evaluate {} '%' {}", repr(lhs), repr(rhs)));
1401 [[nodiscard]]
friend constexpr datum
pow(datum
const &lhs, datum
const &rhs)
1403 if (ttlet doubles = promote_if<double>(lhs, rhs)) {
1404 return datum{
pow(doubles.lhs(), doubles.rhs())};
1406 }
else if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1407 return datum{
pow(long_longs.lhs(), long_longs.rhs())};
1410 throw std::domain_error(std::format(
"Can not evaluate pow({}, {})", repr(lhs), repr(rhs)));
1424 [[nodiscard]]
friend constexpr datum operator&(datum
const &lhs, datum
const &rhs)
1426 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1427 return datum{long_longs.lhs() & long_longs.rhs()};
1429 }
else if (ttlet bools = promote_if<bool>(lhs, rhs)) {
1430 return datum{bools.lhs() and bools.rhs()};
1433 throw std::domain_error(std::format(
"Can not evaluate {} '&' {}", repr(lhs), repr(rhs)));
1447 [[nodiscard]]
friend constexpr datum
operator|(datum
const &lhs, datum
const &rhs)
1449 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1450 return datum{long_longs.lhs() | long_longs.rhs()};
1452 }
else if (ttlet bools = promote_if<bool>(lhs, rhs)) {
1453 return datum{bools.lhs() or bools.rhs()};
1456 throw std::domain_error(std::format(
"Can not evaluate {} '|' {}", repr(lhs), repr(rhs)));
1470 [[nodiscard]]
friend constexpr datum operator^(datum
const &lhs, datum
const &rhs)
1472 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1473 return datum{long_longs.lhs() ^ long_longs.rhs()};
1475 }
else if (ttlet bools = promote_if<bool>(lhs, rhs)) {
1476 return datum{bools.lhs() != bools.rhs()};
1479 throw std::domain_error(std::format(
"Can not evaluate {} '^' {}", repr(lhs), repr(rhs)));
1495 [[nodiscard]]
friend constexpr datum operator<<(datum
const &lhs, datum
const &rhs)
1497 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1498 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1499 throw std::domain_error(std::format(
"Invalid shift count {} '<<' {}", repr(lhs), repr(rhs)));
1501 return datum{long_longs.lhs() << long_longs.rhs()};
1504 throw std::domain_error(std::format(
"Can not evaluate {} '<<' {}", repr(lhs), repr(rhs)));
1519 [[nodiscard]]
friend constexpr datum operator>>(datum
const &lhs, datum
const &rhs)
1521 if (ttlet long_longs = promote_if<long long>(lhs, rhs)) {
1522 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1523 throw std::domain_error(std::format(
"Invalid shift count {} '>>' {}", repr(lhs), repr(rhs)));
1525 return datum{long_longs.lhs() >> long_longs.rhs()};
1528 throw std::domain_error(std::format(
"Can not evaluate {} '>>' {}", repr(lhs), repr(rhs)));
1538 [[nodiscard]] friend constexpr auto operator op(datum const &lhs, auto const &rhs) noexcept(noexcept(lhs op datum{rhs})) \
1540 return lhs op datum{rhs}; \
1542 [[nodiscard]] friend constexpr auto operator op(auto const &lhs, datum const &rhs) noexcept(noexcept(datum{lhs} op rhs)) \
1544 return datum{lhs} op rhs; \
1561 [[nodiscard]]
friend std::string repr(datum
const &rhs)
noexcept
1564 case tag_type::monostate:
return "undefined";
1565 case tag_type::floating_point:
return std::format(
"{:.1f}", rhs._value._double);
1566 case tag_type::decimal:
return to_string(rhs._value._decimal);
1567 case tag_type::integral:
return std::format(
"{}", rhs._value._long_long);
1568 case tag_type::boolean:
return rhs._value._bool ?
"true" :
"false";
1569 case tag_type::year_month_day:
return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1570 case tag_type::null:
return "null";
1571 case tag_type::flow_break:
return "break";
1572 case tag_type::flow_continue:
return "continue";
1573 case tag_type::string:
return std::format(
"\"{}\"", *rhs._value._string);
1574 case tag_type::url:
return to_string(*rhs._value._url);
1575 case tag_type::vector: {
1577 for (ttlet &item : *rhs._value._vector) {
1584 case tag_type::map: {
1586 for (ttlet &item : *rhs._value._map) {
1587 r += repr(item.first);
1589 r += repr(item.second);
1595 case tag_type::bstring:
return base64::encode(*rhs._value._bstring);
1596 default: tt_no_default();
1613 template<
typename T>
1616 if constexpr (std::is_same_v<T, double>) {
1617 return rhs._tag == tag_type::floating_point;
1618 }
else if constexpr (std::is_same_v<T, decimal>) {
1619 return rhs._tag == tag_type::decimal;
1620 }
else if constexpr (std::is_same_v<T, long long>) {
1621 return rhs._tag == tag_type::integral;
1622 }
else if constexpr (std::is_same_v<T, bool>) {
1623 return rhs._tag == tag_type::boolean;
1624 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1625 return rhs._tag == tag_type::year_month_day;
1626 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1627 return rhs._tag == tag_type::null;
1628 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1629 return rhs._tag == tag_type::monostate;
1630 }
else if constexpr (std::is_same_v<T, break_type>) {
1631 return rhs._tag == tag_type::flow_break;
1632 }
else if constexpr (std::is_same_v<T, continue_type>) {
1633 return rhs._tag == tag_type::flow_continue;
1634 }
else if constexpr (std::is_same_v<T, std::string>) {
1635 return rhs._tag == tag_type::string;
1636 }
else if constexpr (std::is_same_v<T, vector_type>) {
1637 return rhs._tag == tag_type::vector;
1638 }
else if constexpr (std::is_same_v<T, map_type>) {
1639 return rhs._tag == tag_type::map;
1640 }
else if constexpr (std::is_same_v<T, URL>) {
1641 return rhs._tag == tag_type::url;
1642 }
else if constexpr (std::is_same_v<T, bstring>) {
1643 return rhs._tag == tag_type::bstring;
1645 tt_static_no_default();
1662 template<
typename To>
1665 if constexpr (std::is_same_v<To, double>) {
1666 return holds_alternative<double>(rhs) or holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or
1667 holds_alternative<bool>(rhs);
1668 }
else if constexpr (std::is_same_v<To, decimal>) {
1669 return holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1670 }
else if constexpr (std::is_same_v<To, long long>) {
1671 return holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1672 }
else if constexpr (std::is_same_v<To, std::string>) {
1673 return holds_alternative<URL>(rhs) or holds_alternative<std::string>(rhs);
1674 }
else if constexpr (std::is_same_v<To, URL>) {
1675 return holds_alternative<URL>(rhs) or holds_alternative<std::string>(rhs);
1677 return holds_alternative<To>(rhs);
1689 template<
typename T>
1690 [[nodiscard]]
friend constexpr T
const &
get(
datum const &rhs)
noexcept
1692 tt_axiom(holds_alternative<T>(rhs));
1693 if constexpr (std::is_same_v<T, double>) {
1694 return rhs._value._double;
1695 }
else if constexpr (std::is_same_v<T, decimal>) {
1696 return rhs._value._decimal;
1697 }
else if constexpr (std::is_same_v<T, long long>) {
1698 return rhs._value._long_long;
1699 }
else if constexpr (std::is_same_v<T, bool>) {
1700 return rhs._value._bool;
1701 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1702 return rhs._value._year_month_day;
1703 }
else if constexpr (std::is_same_v<T, std::string>) {
1704 return *rhs._value._string;
1705 }
else if constexpr (std::is_same_v<T, vector_type>) {
1706 return *rhs._value._vector;
1707 }
else if constexpr (std::is_same_v<T, map_type>) {
1708 return *rhs._value._map;
1709 }
else if constexpr (std::is_same_v<T, URL>) {
1710 return *rhs._value._url;
1711 }
else if constexpr (std::is_same_v<T, bstring>) {
1712 return *rhs._value._bstring;
1714 tt_static_no_default();
1726 template<
typename T>
1727 [[nodiscard]]
friend constexpr T &
get(
datum &rhs)
noexcept
1729 tt_axiom(holds_alternative<T>(rhs));
1730 if constexpr (std::is_same_v<T, double>) {
1731 return rhs._value._double;
1732 }
else if constexpr (std::is_same_v<T, decimal>) {
1733 return rhs._value._decimal;
1734 }
else if constexpr (std::is_same_v<T, long long>) {
1735 return rhs._value._long_long;
1736 }
else if constexpr (std::is_same_v<T, bool>) {
1737 return rhs._value._bool;
1738 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1739 return rhs._value._year_month_day;
1740 }
else if constexpr (std::is_same_v<T, std::string>) {
1741 return *rhs._value._string;
1742 }
else if constexpr (std::is_same_v<T, vector_type>) {
1743 return *rhs._value._vector;
1744 }
else if constexpr (std::is_same_v<T, map_type>) {
1745 return *rhs._value._map;
1746 }
else if constexpr (std::is_same_v<T, URL>) {
1747 return *rhs._value._url;
1748 }
else if constexpr (std::is_same_v<T, bstring>) {
1749 return *rhs._value._bstring;
1751 tt_static_no_default();
1763 template<
typename T>
1766 if (holds_alternative<T>(rhs)) {
1767 return &get<T>(rhs);
1781 template<
typename T>
1782 [[nodiscard]]
friend constexpr T
const *
get_if(
datum const &rhs)
noexcept
1784 if (holds_alternative<T>(rhs)) {
1785 return &get<T>(rhs);
1800 template<
typename T>
1803 if (
auto *value = rhs.find_one(path)) {
1804 if (holds_alternative<T>(*value)) {
1805 return &get<T>(*value);
1823 template<
typename T>
1826 if (
auto *value =
const_cast<datum &
>(rhs).
find_one(path)) {
1827 if (holds_alternative<T>(*value)) {
1828 return &get<T>(*value);
1843 template<
typename To>
1847 if (holds_alternative<To>(lhs) and holds_alternative<To>(rhs)) {
1848 r.set(get<To>(lhs), get<To>(rhs));
1850 }
else if (holds_alternative<To>(lhs) and promotable_to<To>(rhs)) {
1851 r.set(get<To>(lhs),
static_cast<To
>(rhs));
1853 }
else if (promotable_to<To>(lhs) and holds_alternative<To>(rhs)) {
1854 r.set(
static_cast<To
>(lhs), get<To>(rhs));
1861 enum class tag_type :
signed char {
1881 tag_type _tag = tag_type::monostate;
1884 long long _long_long;
1887 std::chrono::year_month_day _year_month_day;
1889 vector_type *_vector;
1894 constexpr value_type(numeric_integral
auto value) noexcept : _long_long(
static_cast<long long>(value)) {}
1895 constexpr value_type(std::floating_point
auto value) noexcept : _double(
static_cast<double>(value)) {}
1896 constexpr value_type(decimal value) noexcept : _decimal(value) {}
1897 constexpr value_type(
bool value) noexcept : _bool(value) {}
1898 constexpr value_type(std::chrono::year_month_day value) noexcept : _year_month_day(value) {}
1899 constexpr value_type(
std::string *value) noexcept : _string(value) {}
1900 constexpr value_type(vector_type *value) noexcept : _vector(value) {}
1901 constexpr value_type(map_type *value) noexcept : _map(value) {}
1902 constexpr value_type(URL *value) noexcept : _url(value) {}
1903 constexpr value_type(bstring *value) noexcept : _bstring(value) {}
1908 [[nodiscard]]
constexpr bool is_scalar() const noexcept
1910 return to_underlying(_tag) >= 0;
1913 [[nodiscard]]
constexpr bool is_pointer() const noexcept
1915 return to_underlying(_tag) < 0;
1918 tt_no_inline
void copy_pointer(datum
const &other)
noexcept
1920 tt_axiom(other.is_pointer());
1921 switch (other._tag) {
1922 case tag_type::string: _value._string =
new std::string{*other._value._string};
return;
1923 case tag_type::vector: _value._vector =
new vector_type{*other._value._vector};
return;
1924 case tag_type::map: _value._map =
new map_type{*other._value._map};
return;
1925 case tag_type::url: _value._url =
new URL{*other._value._url};
return;
1926 case tag_type::bstring: _value._bstring =
new bstring{*other._value._bstring};
return;
1927 default: tt_no_default();
1931 tt_no_inline
void _delete_pointer() noexcept
1933 tt_axiom(is_pointer());
1935 case tag_type::string:
delete _value._string;
return;
1936 case tag_type::vector:
delete _value._vector;
return;
1937 case tag_type::map:
delete _value._map;
return;
1938 case tag_type::url:
delete _value._url;
return;
1939 case tag_type::bstring:
delete _value._bstring;
return;
1940 default: tt_no_default();
1944 constexpr void delete_pointer() noexcept
1951 void find_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *> &r)
noexcept
1953 if (
auto vector = get_if<datum::vector_type>(*
this)) {
1954 for (
auto &item : *vector) {
1955 item.find(it + 1, it_end, r);
1958 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
1959 for (
auto &item : *map) {
1960 item.second.find(it + 1, it_end, r);
1965 void find_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *> &r)
noexcept
1967 this->find(it + 1, it_end, r);
1969 if (
auto vector = get_if<datum::vector_type>(*
this)) {
1970 for (
auto &item : *vector) {
1971 item.find(it, it_end, r);
1974 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
1975 for (
auto &item : *map) {
1976 item.second.find(it, it_end, r);
1982 jsonpath_indices
const &indices,
1983 jsonpath::const_iterator it,
1984 jsonpath::const_iterator it_end,
1987 if (
auto vector = get_if<datum::vector_type>(*
this)) {
1988 for (ttlet index : indices.filter(
std::ssize(*vector))) {
1989 (*vector)[index].find(it + 1, it_end, r);
1995 jsonpath_names
const &names,
1996 jsonpath::const_iterator it,
1997 jsonpath::const_iterator it_end,
2000 if (
auto map = get_if<datum::map_type>(*
this)) {
2001 for (ttlet &name : names) {
2002 ttlet name_ = datum{name};
2003 auto jt = map->find(name_);
2004 if (jt != map->cend()) {
2005 jt->second.find(it + 1, it_end, r);
2012 jsonpath_slice
const &slice,
2013 jsonpath::const_iterator it,
2014 jsonpath::const_iterator it_end,
2017 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2018 ttlet first = slice.begin(vector->size());
2019 ttlet last = slice.end(vector->size());
2021 for (
auto index = first; index != last; index += slice.step) {
2022 if (index >= 0 and index < vector->size()) {
2023 (*this)[index].find(it + 1, it_end, r);
2029 void find(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *> &r)
noexcept
2034 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2035 find(it + 1, it_end, r);
2037 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2038 find(it + 1, it_end, r);
2040 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2041 find_wildcard(it, it_end, r);
2043 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2044 find_descend(it, it_end, r);
2046 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2047 find_indices(*indices, it, it_end, r);
2049 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2050 find_names(*names, it, it_end, r);
2052 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2053 find_slice(*slice, it, it_end, r);
2060 [[nodiscard]]
int remove_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2064 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2065 auto jt = vector->begin();
2066 while (jt != vector->end()) {
2067 ttlet match = jt->remove(it + 1, it_end);
2071 jt = vector->erase(jt);
2076 return vector->empty() ? 2 : r;
2078 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2079 auto jt = map->begin();
2080 while (jt != map->end()) {
2081 ttlet match = jt->second.remove(it + 1, it_end);
2085 jt = map->erase(jt);
2090 return map->empty() ? 2 : r;
2097 [[nodiscard]]
int remove_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2102 ttlet match = this->
remove(it + 1, it_end);
2109 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2110 auto jt = vector->begin();
2111 while (jt != vector->end()) {
2112 ttlet match = jt->remove(it, it_end);
2116 jt = vector->erase(jt);
2121 return vector->empty() ? 2 : r;
2123 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2124 auto jt = map->begin();
2125 while (jt != map->end()) {
2126 ttlet match = jt->second.remove(it, it_end);
2130 jt = map->erase(jt);
2135 return map->empty() ? 2 : r;
2143 remove_indices(jsonpath_indices
const &indices, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2145 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2149 for (ttlet index : indices.filter(
std::ssize(*vector))) {
2150 ttlet match = (*vector)[index - offset].remove(it + 1, it_end);
2153 vector->erase(vector->begin() + (index - offset));
2158 return vector->empty() ? 2 : r;
2166 remove_names(jsonpath_names
const &names, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2168 if (
auto map = get_if<datum::map_type>(*
this)) {
2171 for (ttlet &name : names) {
2172 ttlet name_ = datum{name};
2173 auto jt = map->find(name_);
2174 if (jt != map->cend()) {
2175 ttlet match = jt->second.remove(it + 1, it_end);
2183 return map->empty() ? 2 : r;
2191 remove_slice(jsonpath_slice
const &slice, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2193 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2196 ttlet first = slice.begin(vector->size());
2197 ttlet last = slice.end(vector->size());
2200 for (
auto index = first; index != last; index += slice.step) {
2201 if (index >= 0 and index < vector->size()) {
2202 ttlet match = (*this)[index - offset].remove(it + 1, it_end);
2206 vector->erase(vector->begin() + (index - offset));
2212 return vector->empty() ? 2 : r;
2219 [[nodiscard]]
int remove(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2225 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2226 return remove(it + 1, it_end);
2228 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2229 return remove(it + 1, it_end);
2231 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2232 return remove_wildcard(it, it_end);
2234 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2235 return remove_descend(it, it_end);
2237 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2238 return remove_indices(*indices, it, it_end);
2240 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2241 return remove_names(*names, it, it_end);
2243 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2244 return remove_slice(*slice, it, it_end);
2251 [[nodiscard]] datum *
2252 find_one_name(datum
const &name, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2254 tt_axiom(holds_alternative<std::string>(name));
2256 if (
auto *map = get_if<map_type>(*
this)) {
2257 auto i = map->find(name);
2258 if (i != map->end()) {
2259 return i->second.find_one(it + 1, it_end, create);
2261 }
else if (create) {
2262 (*map)[name] = datum{std::monostate{}};
2263 return find_one_name(name, it, it_end, create);
2269 }
else if (holds_alternative<std::monostate>(*
this) and create) {
2270 *
this = datum::make_map(name, std::monostate{});
2271 return find_one_name(name, it, it_end, create);
2278 [[nodiscard]] datum *
2279 find_one_index(
size_t index, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2281 if (
auto *vector = get_if<vector_type>(*
this)) {
2282 if (index < vector->size()) {
2283 return (*vector)[index].find_one(it + 1, it_end, create);
2284 }
else if (index == vector->size() and create) {
2285 vector->push_back(datum{std::monostate{}});
2286 return find_one_index(index, it, it_end, create);
2291 }
else if (holds_alternative<std::monostate>(*
this) and index == 0 and create) {
2292 *
this = datum::make_vector(std::monostate{});
2293 return find_one_index(index, it, it_end, create);
2300 [[nodiscard]] datum *
find_one(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2305 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2306 return find_one(it + 1, it_end, create);
2308 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2309 return find_one(it + 1, it_end, create);
2311 }
else if (ttlet *indices = std::get_if<jsonpath_indices>(&*it)) {
2312 tt_axiom(indices->size() == 1);
2313 return find_one_index(indices->front(), it, it_end, create);
2315 }
else if (ttlet *names = std::get_if<jsonpath_names>(&*it)) {
2316 tt_axiom(names->size() == 1);
2317 return find_one_name(datum{names->front()}, it, it_end, create);