Skip to content

Commit

Permalink
normalized_path_parser
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Nov 17, 2023
1 parent dc48da6 commit e231692
Show file tree
Hide file tree
Showing 7 changed files with 621 additions and 78 deletions.
114 changes: 114 additions & 0 deletions doc/ref/jsonpath/basic_path_element.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
### jsoncons::jsonpath::basic_path_element

```cpp
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

template <class CharT>
class basic_path_element
```
Two specializations for common character types are defined:
Type |Definition
----------|------------------------------
path_element |`basic_path_element<char>` (since 0.172.0)
wpath_element |`basic_path_element<wchar_t>` (since 0.172.0)
Objects of type `basic_path_element` represent a normalized path.
#### Member types
Type |Definition
------------|------------------------------
char_type | `CharT`
string_type | `std::basic_string<char_type>`
string_view_type | `jsoncons::basic_string_view<char_type>`
const_iterator | A constant [LegacyRandomAccessIterator](https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator) with a `value_type` of `std::basic_string<char_type>`
iterator | An alias to `const_iterator`
#### Constructors
basic_path_element(); (1)
explicit basic_path_element(const string_view_type& str);
explicit basic_path_element(const string_view_type& str,
std::error_code& ec); (2)
basic_path_element(const basic_path_element&); (3)
basic_path_element(basic_path_element&&) noexcept; (4)
(1) Constructs an empty `basic_path_element`.
(2) Constructs a `basic_path_element` from a string representation or a
URI fragment identifier (starts with `#`).
#### operator=
basic_path_element& operator=(const basic_path_element&);
basic_path_element& operator=(basic_path_element&&);
#### Modifiers
basic_path_element& operator/=(const string_type& s)
Appends the token s.
template <class IntegerType>
basic_path_element& operator/=(IntegerType index)
Appends the token `index`.
This overload only participates in overload resolution if `IntegerType` is an integer type.
basic_path_element& operator+=(const basic_path_element& ptr)
Concatenates the current pointer and the specified pointer `ptr`.
#### Iterators
iterator begin() const;
iterator end() const;
Iterator access to the tokens in the pointer.
#### Accessors
bool empty() const
Checks if the pointer is empty
string_type to_string() const
Returns a normalized path represented as a string value, escaping any `/` or `~` characters.
string_type to_uri_fragment() const
Returns a string representing the normalized path as a URI fragment identifier,
escaping any `/` or `~` characters.
#### Static member functions
static parse(const string_view_type& str);
static parse(const string_view_type& str, std::error_code& ec);
Constructs a `basic_path_element` from a string representation or a
URI fragment identifier (starts with `#`).
#### Non-member functions
basic_path_element<CharT> operator/(const basic_path_element<CharT>& lhs, const basic_string<CharT>& s);
Concatenates a normalized path pointer and a string. Effectively returns basic_path_element<CharT>(lhs) /= s.
template <class CharT,class IntegerType>
basic_path_element<CharT> operator/(const basic_path_element<CharT>& lhs, IntegerType index);
Concatenates a normalized path pointer and an index. Effectively returns basic_path_element<CharT>(lhs) /= index.
This overload only participates in overload resolution if `IntegerType` is an integer type.
template <class CharT,class IntegerType>
basic_path_element<CharT> operator+( const basic_path_element<CharT>& lhs, const basic_path_element<CharT>& rhs );
Concatenates two normalized paths. Effectively returns basic_path_element<CharT>(lhs) += rhs.
template <class CharT,class IntegerType>
bool operator==(const basic_path_element<CharT>& lhs, const basic_path_element<CharT>& rhs);
template <class CharT,class IntegerType>
bool operator!=(const basic_path_element<CharT>& lhs, const basic_path_element<CharT>& rhs);
template <class CharT,class IntegerType>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_path_element<CharT>& ptr);
Performs stream output
92 changes: 14 additions & 78 deletions include/jsoncons_ext/jsonpath/json_location.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,86 +10,11 @@
#include <string>
#include <vector>
#include <jsoncons/config/jsoncons_config.hpp>
#include <jsoncons_ext/jsonpath/jsonpath_utilities.hpp>
#include <jsoncons_ext/jsonpath/normalized_path_parser.hpp>

namespace jsoncons {
namespace jsonpath {

template <class CharT,class Allocator>
class basic_path_element
{
public:
using char_type = CharT;
using allocator_type = Allocator;
using char_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT>;
using string_type = std::basic_string<char_type,std::char_traits<char_type>,char_allocator_type>;
private:
bool has_name_;
string_type name_;
std::size_t index_;

public:
basic_path_element(const string_type& name)
: has_name_(true), name_(name), index_(0)
{
}

basic_path_element(string_type&& name)
: has_name_(true), name_(std::move(name)), index_(0)
{
}

basic_path_element(std::size_t index)
: has_name_(false), index_(index)
{
}

basic_path_element(const basic_path_element& other) = default;

basic_path_element& operator=(const basic_path_element& other) = default;

bool has_name() const
{
return has_name_;
}

bool has_index() const
{
return !has_name_;
}

const string_type& name() const
{
return name_;
}

std::size_t index() const
{
return index_;
}

int compare(const basic_path_element& other) const
{
int diff = 0;
if (has_name_ != other.has_name_)
{
diff = static_cast<int>(has_name_) - static_cast<int>(other.has_name_);
}
else
{
if (has_name_)
{
diff = name_.compare(other.name_);
}
else
{
diff = index_ < other.index_ ? -1 : index_ > other.index_ ? 1 : 0;
}
}
return diff;
}
};

template <class CharT, class Allocator = std::allocator<CharT>>
class basic_json_location
{
Expand All @@ -113,6 +38,11 @@ namespace jsonpath {
{
}

basic_json_location(std::vector<path_element_type>&& elements)
: elements_(std::move(elements))
{
}

iterator begin()
{
return elements_.begin();
Expand Down Expand Up @@ -216,6 +146,14 @@ namespace jsonpath {
{
return lhs.compare(rhs) < 0;
}

static basic_json_location parse(const jsoncons::basic_string_view<char_type>& normalized_path)
{
jsonpath::detail::normalized_path_parser<char,std::allocator<char>> parser;

std::vector<jsonpath::path_element> location = parser.parse(normalized_path);
return basic_json_location(std::move(location));
}
};

template<class Json>
Expand Down Expand Up @@ -361,8 +299,6 @@ namespace jsonpath {

using json_location = basic_json_location<char>;
using wjson_location = basic_json_location<wchar_t>;
using path_element = basic_path_element<char,std::allocator<char>>;
using wpath_element = basic_path_element<wchar_t,std::allocator<char>>;

inline
std::string to_string(const json_location& location)
Expand Down
9 changes: 9 additions & 0 deletions include/jsoncons_ext/jsonpath/jsonpath_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ namespace jsoncons { namespace jsonpath {
enum class jsonpath_errc
{
success = 0,
expected_root_or_current_node,
expected_lbracket,
expected_single_quote_or_digit,
expected_root_or_function,
expected_current_node,
expected_rparen,
Expand Down Expand Up @@ -65,6 +68,12 @@ namespace jsoncons { namespace jsonpath {
{
switch (static_cast<jsonpath_errc>(ev))
{
case jsonpath_errc::expected_root_or_current_node:
return "Expected '$' or '@'";
case jsonpath_errc::expected_lbracket:
return "Expected '['";
case jsonpath_errc::expected_single_quote_or_digit:
return "Expected '\'' or digit";
case jsonpath_errc::expected_root_or_function:
return "Expected '$' or function expression";
case jsonpath_errc::expected_current_node:
Expand Down
Loading

0 comments on commit e231692

Please sign in to comment.