30 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
42 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
54 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
66 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
73 constexpr names(
names const&)
noexcept =
default;
75 constexpr names& operator=(
names const&)
noexcept =
default;
76 constexpr names& operator=(
names&&)
noexcept =
default;
77 constexpr names()
noexcept =
default;
88 for (hilet& name : *
this) {
102 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
113 constexpr indices()
noexcept =
default;
119 for (hilet index : *
this) {
124 r += hi::to_string(index);
135 for (hilet index : *
this) {
143 [[
nodiscard]]
constexpr bool is_singular()
const noexcept
154 constexpr slice(
slice const&)
noexcept =
default;
156 constexpr slice& operator=(
slice const&)
noexcept =
default;
157 constexpr slice& operator=(
slice&&)
noexcept =
default;
159 constexpr slice(ptrdiff_t first, ptrdiff_t last, ptrdiff_t step)
noexcept : first(first), last(last), step(step) {}
161 [[
nodiscard]]
constexpr bool last_is_empty()
const noexcept
174 hilet
begin = first >= 0 ? first :
size_ + first;
188 if (last_is_empty()) {
193 hilet
end = last >= 0 ? last :
size_ + last;
198 hilet
steps = distance / step;
205 if (last_is_empty()) {
206 return std::format(
"[{}:e:{}]", first, step);
208 return std::format(
"[{}:{}:{}]", first, last, step);
218 using node = std::variant<root, current, wildcard, descend, names, indices, slice>;
220 using value_type =
typename container_type::value_type;
221 using iterator =
typename container_type::iterator;
222 using const_iterator =
typename container_type::const_iterator;
224 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
225 [[
nodiscard]]
constexpr jsonpath(
It it, ItEnd last) : _nodes()
227 auto lexer_it = lexer<lexer_config::json_style()>.parse(
it, last);
230 while (
token_it != std::default_sentinel) {
238 hi_check(_nodes.
empty(),
"Root node '$' not at start of path.");
243 hi_check(_nodes.
empty(),
"Current node '@' not at start of path.");
247 }
else if (*
token_it == token::id) {
248 hi_check(_nodes.
empty(),
"Unexpected child name {}.", *
token_it);
253 throw parse_error(std::format(
"Unexpected token {}.", *
token_it));
258 [[
nodiscard]]
constexpr jsonpath(std::string_view rhs) : jsonpath(rhs.begin(), rhs.end()) {}
262 return _nodes.
empty();
270 for (hilet& node : _nodes) {
273 return node_.is_singular();
282 return _nodes.
size();
287 return _nodes.
begin();
292 return _nodes.
begin();
312 return _nodes.
cend();
318 for (hilet& node : path._nodes) {
321 return node_.string();
331 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
332 [[
nodiscard]]
constexpr static node parse_slicing_operator(
It&
it, ItEnd last)
338 if (
it.size() >= 2
and it[0] ==
'-' and it[1] == token::integer) {
339 auto tmp =
static_cast<size_t>(
it[1]);
344 }
else if (*
it == token::integer) {
345 auto tmp =
static_cast<size_t>(*it);
350 }
else if (*
it ==
':') {
354 throw parse_error(std::format(
"Unexpected token while parsing start-index of the slicing operator, got {}", *
it));
357 hi_check(
it != last,
"Unexpected end-of-text after the start-index of the slicing operator.");
358 hi_check(*
it ==
':',
"Expecting ':' adter the start-index of the slicing operator, got {}", *
it);
361 hi_check(
it != last,
"Unexpected end-of-text while parsing the end-index of the slicing operator.");
364 return slice{start, end, step};
366 }
else if (
it.size() >= 2
and it[0] ==
'-' and it[1] == token::integer) {
367 auto tmp =
static_cast<size_t>(
it[1]);
372 }
else if (*
it == token::integer) {
373 auto tmp =
static_cast<size_t>(*it);
378 }
else if (*
it ==
':' or *
it ==
']') {
382 throw parse_error(std::format(
"Unexpected token while parsing the end-index of the slicing operator, got {}", *
it));
385 hi_check(
it != last,
"Unexpected end-of-text after the end-index of the slicing operator.");
388 return slice{start, end, step};
390 }
else if (
it.size() >= 2
and it[0] ==
'-' and it[1] == token::integer) {
391 auto tmp =
static_cast<size_t>(
it[1]);
396 }
else if (*
it == token::integer) {
397 auto tmp =
static_cast<size_t>(*it);
403 throw parse_error(std::format(
"Unexpected token while parsing step-value of the slicing operator, got {}", *
it));
406 hi_check(
it != last,
"Unexpected end-of-text after the step-value of the slicing operator.");
407 hi_check(*
it ==
']',
"Expecting '] after step-value of the slicing operator, got {}", *
it);
409 return slice{start, end, step};
412 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
413 [[
nodiscard]]
constexpr static node parse_integer_indexing_operator(
It&
it, ItEnd last)
418 if (
it.size() >= 2
and it[0] ==
'-' and it[1] == token::integer) {
419 auto tmp =
static_cast<size_t>(
it[1]);
424 }
else if (*
it == token::integer) {
425 auto tmp =
static_cast<size_t>(*it);
431 throw parse_error(std::format(
"Expected an integer-index, got {}", *
it));
435 throw parse_error(
"Unexpected end-of-text while parsing the index operator '['.");
437 }
else if (*
it ==
']') {
441 }
else if (*
it ==
',') {
446 throw parse_error(std::format(
"Unexpected token after a integer-index: {}.", *
it));
451 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
452 [[
nodiscard]]
constexpr static node parse_name_indexing_operator(
It&
it, ItEnd last)
457 if (*
it != token::id
and *
it != token::sstr
and *
it != token::dstr) {
458 throw parse_error(std::format(
"Expected a name-index, got {}", *
it));
464 throw parse_error(
"Unexpected end-of-text while parsing the index operator '['.");
466 }
else if (*
it ==
']') {
470 }
else if (*
it ==
',') {
475 throw parse_error(std::format(
"Unexpected token after a name-index: {}.", *
it));
480 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
481 [[
nodiscard]]
constexpr static node parse_indexing_operator(
It&
it, ItEnd last)
483 hi_check(
it != last,
"Unexpected end-of-text at index operator token '['.");
486 hi_check(
it.size() >= 2
and it[1] ==
']',
"Expected end of wildcast-indexing operator '[*', got {}.",
it[1]);
492 (
it.size() >= 3
and it[0] ==
'-' and it[1] == token::integer
and it[2] ==
':')) {
493 return parse_slicing_operator(
it, last);
495 }
else if (*
it == token::integer
or (
it.size() >= 2
and it[0] ==
'-' and it[1] == token::integer)) {
496 return parse_integer_indexing_operator(
it, last);
498 }
else if (*
it == token::id
or *
it == token::sstr
or *
it == token::dstr) {
499 return parse_name_indexing_operator(
it, last);
503 std::format(
"Expected a integer index or name-index after indexing operator '[', got token {}.", *
it));
507 template<std::input_iterator It, std::sentinel_for<It> ItEnd>
508 [[
nodiscard]]
constexpr static node parse_child_operator(
It&
it, ItEnd last)
510 hi_check(
it != last,
"Unexpected end-of-text at child operator token '.'.");
516 }
else if (*
it ==
'.') {
517 if (
it.size() >= 2
and it[1] ==
'[') {
530 }
else if (*
it == token::id) {
536 throw parse_error(std::format(
"Expected a child name or wildcard, got token {}.", *
it));