diff options
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp')
-rw-r--r-- | vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp | 1495 |
1 files changed, 1495 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp new file mode 100644 index 00000000..b0ac51c6 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp @@ -0,0 +1,1495 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_JSONPATH_FILTER_HPP +#define JSONCONS_JSONPATH_FILTER_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <memory> +#include <regex> +#include "jsoncons/json.hpp" +#include "jsonpath_error_category.hpp" + +namespace jsoncons { namespace jsonpath { + +template <class JsonT> +class jsonpath_evaluator; + +enum class filter_states +{ + start, + cr, + lf, + expect_right_round_bracket, + expect_oper_or_right_round_bracket, + expect_path_or_value, + expect_regex, + regex, + single_quoted_text, + double_quoted_text, + unquoted_text, + path, + value, + oper +}; + +enum class token_types +{ + left_paren, + right_paren, + term, + eq, + ne, + regex, + ampamp, + pipepipe, + lt, + gt, + lte, + gte, + plus, + minus, + exclaim, + done +}; + +template <class JsonT> +class term +{ +public: + typedef typename JsonT::string_type string_type; + typedef typename JsonT::char_type char_type; + + virtual void initialize(const JsonT& context_node) + { + } + virtual bool accept_single_node() const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT evaluate_single_node() const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool exclaim() const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool eq(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool eq(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool ne(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool ne(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool regex(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool regex2(const string_type& subject) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool ampamp(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool ampamp(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool pipepipe(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool pipepipe(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool lt(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool lt(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool gt(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual bool gt(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT minus(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT minus(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT unary_minus() const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT plus(const term& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } + virtual JsonT plus(const JsonT& rhs) const + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unsupported_operator, jsonpath_error_category()),1,1); + } +}; + +template <class JsonT> +class token +{ + token_types type_; + std::shared_ptr<term<JsonT>> term_ptr_; +public: + token(token_types type) + : type_(type) + { + } + token(token_types type, std::shared_ptr<term<JsonT>> term_ptr) + : type_(type), term_ptr_(term_ptr) + { + } + token(const token& t) + : type_(t.type_), term_ptr_(t.term_ptr_) + { + } + + token_types type() const + { + return type_; + } + + std::shared_ptr<term<JsonT>> term_ptr() + { + return term_ptr_; + } + + void initialize(const JsonT& context_node) + { + if (term_ptr_.get() != nullptr) + { + term_ptr_->initialize(context_node); + } + } +}; + +template <class JsonT> +class token_stream +{ + std::vector<token<JsonT>>& tokens_; + size_t index_; +public: + token_stream(std::vector<token<JsonT>>& tokens) + : tokens_(tokens), index_(0) + { + } + + token<JsonT> get() + { + static token<JsonT> done = token<JsonT>(token_types::done); + return index_ < tokens_.size() ? tokens_[index_++] : done; + } + void putback() + { + --index_; + } +}; + +template <class JsonT> +bool ampamp(const JsonT& lhs, const JsonT& rhs) +{ + return lhs.as_bool() && rhs.as_bool(); +} + +template <class JsonT> +bool pipepipe(const JsonT& lhs, const JsonT& rhs) +{ + return lhs.as_bool() || rhs.as_bool(); +} + +template <class JsonT> +bool lt(const JsonT& lhs, const JsonT& rhs) +{ + bool result = false; + if (lhs. template is<unsigned long long>() && rhs. template is<unsigned long long>()) + { + result = lhs. template as<unsigned long long>() < rhs. template as<unsigned long long>(); + } + else if (lhs. template is<long long>() && rhs. template is<long long>()) + { + result = lhs. template as<long long>() < rhs. template as<long long>(); + } + else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number())) + { + result = lhs.as_double() < rhs.as_double(); + } + else if (lhs.is_string() && rhs.is_string()) + { + result = lhs.as_string() < rhs.as_string(); + } + return result; +} + +template <class JsonT> +bool gt(const JsonT& lhs, const JsonT& rhs) +{ + return lt(rhs,lhs); +} + +template <class JsonT> +JsonT plus(const JsonT& lhs, const JsonT& rhs) +{ + JsonT result = jsoncons::null_type(); + if (lhs.is_integer() && rhs.is_integer()) + { + result = ((lhs.as_integer() + rhs.as_integer())); + } + else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number())) + { + result = (lhs.as_double() + rhs.as_double()); + } + else if (lhs.is_uinteger() && rhs.is_uinteger()) + { + result = (lhs.as_uinteger() + rhs.as_uinteger()); + } + return result; +} + +template <class JsonT> +JsonT unary_minus(const JsonT& lhs) +{ + JsonT result = jsoncons::null_type(); + if (lhs.is_integer()) + { + result = -lhs.as_integer(); + } + else if (lhs.is_double()) + { + result = -lhs.as_double(); + } + return result; +} + +template <class JsonT> +JsonT minus(const JsonT& lhs, const JsonT& rhs) +{ + JsonT result = jsoncons::null_type(); + if (lhs.is_integer() && rhs.is_integer()) + { + result = ((lhs.as_integer() - rhs.as_integer())); + } + else if ((lhs.is_number() && rhs.is_double()) || (lhs.is_double() && rhs.is_number())) + { + result = (lhs.as_double() - rhs.as_double()); + } + else if (lhs.is_uinteger() && rhs.is_uinteger() && lt(rhs,lhs)) + { + result = (lhs.as_uinteger() - rhs.as_uinteger()); + } + return result; +} + +template <class JsonT> +class value_term : public term<JsonT> +{ + JsonT value_; +public: + template <class T> + value_term(const T& value) + : value_(value) + { + } + + bool accept_single_node() const override + { + return value_.as_bool(); + } + + JsonT evaluate_single_node() const override + { + return value_; + } + + bool exclaim() const override + { + return !value_.as_bool(); + } + + bool eq(const term<JsonT>& rhs) const override + { + return rhs.eq(value_); + } + + bool eq(const JsonT& rhs) const override + { + return value_ == rhs; + } + + bool ne(const term<JsonT>& rhs) const override + { + return rhs.ne(value_); + } + bool ne(const JsonT& rhs) const override + { + return value_ != rhs; + } + bool regex(const term<JsonT>& rhs) const override + { + return rhs.regex2(value_.as_string()); + } + bool ampamp(const term<JsonT>& rhs) const override + { + return rhs.ampamp(value_); + } + bool ampamp(const JsonT& rhs) const override + { + return jsoncons::jsonpath::ampamp(value_,rhs); + } + bool pipepipe(const term<JsonT>& rhs) const override + { + return rhs.pipepipe(value_); + } + bool pipepipe(const JsonT& rhs) const override + { + return jsoncons::jsonpath::pipepipe(value_,rhs); + } + + bool lt(const term<JsonT>& rhs) const override + { + return rhs.gt(value_); + } + + bool lt(const JsonT& rhs) const override + { + return jsoncons::jsonpath::lt(value_,rhs); + } + + bool gt(const term<JsonT>& rhs) const override + { + return rhs.lt(value_); + } + + bool gt(const JsonT& rhs) const override + { + return jsoncons::jsonpath::gt(value_,rhs); + } + + JsonT minus(const term<JsonT>& rhs) const override + { + return jsoncons::jsonpath::plus(rhs.unary_minus(),value_); + } + + JsonT minus(const JsonT& rhs) const override + { + return jsoncons::jsonpath::minus(value_,rhs); + } + + JsonT unary_minus() const override + { + return jsoncons::jsonpath::unary_minus(value_); + } + + JsonT plus(const term<JsonT>& rhs) const override + { + return rhs.plus(value_); + } + + JsonT plus(const JsonT& rhs) const override + { + return jsoncons::jsonpath::plus(value_,rhs); + } +}; + +template <class JsonT> +class regex_term : public term<JsonT> +{ + typedef typename JsonT::char_type char_type; + typedef typename JsonT::string_type string_type; + string_type pattern_; + std::regex::flag_type flags_; +public: + regex_term(const string_type& pattern, std::regex::flag_type flags) + : pattern_(pattern), flags_(flags) + { + } + + bool regex2(const string_type& subject) const override + { + std::basic_regex<char_type> pattern(pattern_, + flags_); + return std::regex_match(subject, pattern); + } +}; + +template <class JsonT> +class path_term : public term<JsonT> +{ + typedef typename JsonT::string_type string_type; + + string_type path_; + JsonT nodes_; +public: + path_term(const string_type& path) + : path_(path) + { + } + + void initialize(const JsonT& context_node) override + { + jsonpath_evaluator<JsonT> evaluator; + evaluator.evaluate(context_node,path_); + nodes_ = evaluator.get_values(); + } + + bool accept_single_node() const override + { + return nodes_.size() != 0; + } + + JsonT evaluate_single_node() const override + { + return nodes_.size() == 1 ? nodes_[0] : nodes_; + } + + bool exclaim() const override + { + return nodes_.size() == 0; + } + + bool eq(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.eq(nodes_[i]); + } + } + return result; + } + + bool eq(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = nodes_[i] == rhs; + } + } + return result; + } + + bool ne(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.ne(nodes_[i]); + } + } + return result; + + } + bool ne(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = nodes_[i] != rhs; + } + } + return result; + } + bool regex(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.regex2(nodes_[i].as_string()); + } + } + return result; + } + bool ampamp(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.ampamp(nodes_[i]); + } + } + return result; + } + bool ampamp(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = jsoncons::jsonpath::ampamp(nodes_[i],rhs); + } + } + return result; + } + bool pipepipe(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.pipepipe(nodes_[i]); + } + } + return result; + } + bool pipepipe(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = jsoncons::jsonpath::pipepipe(nodes_[i],rhs); + } + } + return result; + } + + bool lt(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = jsoncons::jsonpath::lt(nodes_[i],rhs); + } + } + return result; + } + + bool lt(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.gt(nodes_[i]); + } + } + return result; + } + + bool gt(const JsonT& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = jsoncons::jsonpath::gt(nodes_[i],rhs); + } + } + return result; + } + + bool gt(const term<JsonT>& rhs) const override + { + bool result = false; + if (nodes_.size() > 0) + { + result = true; + for (size_t i = 0; result && i < nodes_.size(); ++i) + { + result = rhs.lt(nodes_[i]); + } + } + return result; + } + + JsonT minus(const JsonT& rhs) const override + { + return nodes_.size() == 1 ? jsoncons::jsonpath::minus(nodes_[0],rhs) : jsoncons::null_type(); + } + + JsonT minus(const term<JsonT>& rhs) const override + { + + return nodes_.size() == 1 ? jsoncons::jsonpath::plus(rhs.unary_minus(),nodes_[0]) : jsoncons::null_type(); + } + + JsonT unary_minus() const override + { + return nodes_.size() == 1 ? jsoncons::jsonpath::unary_minus(nodes_[0]) : jsoncons::null_type(); + } + + JsonT plus(const JsonT& rhs) const override + { + static auto a_null = jsoncons::null_type(); + return nodes_.size() == 1 ? jsoncons::jsonpath::plus(nodes_[0],rhs) : a_null; + } + + JsonT plus(const term<JsonT>& rhs) const override + { + static auto a_null = jsoncons::null_type(); + return nodes_.size() == 1 ? rhs.plus(nodes_[0]) : a_null; + } +}; + +template <class JsonT> +class jsonpath_filter_parser +{ + typedef typename JsonT::string_type string_type; + typedef typename JsonT::char_type char_type; + + size_t& line_; + size_t& column_; + filter_states state_; + string_type buffer_; + std::vector<token<JsonT>> tokens_; + int depth_; + const char_type* begin_input_; + const char_type* end_input_; + const char_type*& p_; + filter_states pre_line_break_state_; +public: + jsonpath_filter_parser(const char_type** expr, size_t* line,size_t* column) + : line_(*line), column_(*column),p_(*expr) + { + } + + bool exists(const JsonT& context_node) + { + for (auto it=tokens_.begin(); it != tokens_.end(); ++it) + { + it->initialize(context_node); + } + bool result = false; + + token_stream<JsonT> ts(tokens_); + auto e = expression(ts); + result = e->accept_single_node(); + + return result; + } + + JsonT eval(const JsonT& context_node) + { + try + { + for (auto it=tokens_.begin(); it != tokens_.end(); ++it) + { + it->initialize(context_node); + } + + token_stream<JsonT> ts(tokens_); + auto e = expression(ts); + JsonT result = e->evaluate_single_node(); + + return result; + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + } + + std::shared_ptr<term<JsonT>> primary(token_stream<JsonT>& ts) + { + auto t = ts.get(); + + switch (t.type()) + { + case token_types::left_paren: + { + auto expr = expression(ts); + t = ts.get(); + if (t.type() != token_types::right_paren) + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_right_brace, jsonpath_error_category()),line_,column_); + } + return expr; + } + case token_types::term: + return t.term_ptr(); + case token_types::exclaim: + { + JsonT val = primary(ts)->exclaim(); + auto expr = std::make_shared<value_term<JsonT>>(val); + return expr; + } + case token_types::minus: + { + JsonT val = primary(ts)->unary_minus(); + auto expr = std::make_shared<value_term<JsonT>>(val); + return expr; + } + default: + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_primary, jsonpath_error_category()),line_,column_); + } + } + + std::shared_ptr<term<JsonT>> expression(token_stream<JsonT>& ts) + { + auto left = make_term(ts); + auto t = ts.get(); + while (true) + { + switch (t.type()) + { + case token_types::plus: + { + JsonT val = left->plus(*(make_term(ts))); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::minus: + { + JsonT val = left->minus(*(make_term(ts))); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + default: + ts.putback(); + return left; + } + } + return left; + } + + std::shared_ptr<term<JsonT>> make_term(token_stream<JsonT>& ts) + { + auto left = primary(ts); + auto t = ts.get(); + while (true) + { + switch (t.type()) + { + case token_types::eq: + { + bool e = left->eq(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::ne: + { + bool e = left->ne(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::regex: + { + bool e = left->regex(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::ampamp: + { + bool e = left->ampamp(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::pipepipe: + { + bool e = left->pipepipe(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::lt: + { + bool e = left->lt(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::gt: + { + bool e = left->gt(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::lte: + { + bool e = left->lt(*(primary(ts))) || left->eq(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + case token_types::gte: + { + bool e = left->gt(*(primary(ts))) || left->eq(*(primary(ts))); + JsonT val(e); + left = std::make_shared<value_term<JsonT>>(val); + t = ts.get(); + } + break; + default: + ts.putback(); + return left; + } + } + } + + void parse(const char_type* expr, size_t length) + { + parse(expr,expr+length); + } + + void parse(const char_type* expr, const char_type* end_expr) + { + p_ = expr; + end_input_ = end_expr; + depth_ = 0; + tokens_.clear(); + state_ = filter_states::start; + bool done = false; + while (!done && p_ < end_input_) + { + switch (state_) + { + case filter_states::cr: + ++line_; + column_ = 1; + switch (*p_) + { + case '\n': + state_ = pre_line_break_state_; + ++p_; + ++column_; + break; + default: + state_ = pre_line_break_state_; + break; + } + break; + case filter_states::lf: + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case filter_states::start: + switch (*p_) + { + case '\r': + case '\n': + pre_line_break_state_ = state_; + state_ = filter_states::lf; + break; + case '(': + state_ = filter_states::expect_path_or_value; + ++depth_; + tokens_.push_back(token<JsonT>(token_types::left_paren)); + break; + case ')': + tokens_.push_back(token<JsonT>(token_types::right_paren)); + if (--depth_ == 0) + { + done = true; + } + break; + } + ++p_; + ++column_; + break; + case filter_states::oper: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '!': + if (p_+1 < end_input_ && *(p_+1) == '=') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::ne)); + } + else + { + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::exclaim)); + } + break; + case '&': + if (p_+1 < end_input_ && *(p_+1) == '&') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::ampamp)); + } + break; + case '|': + if (p_+1 < end_input_ && *(p_+1) == '|') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::pipepipe)); + } + break; + case '=': + if (p_+1 < end_input_ && *(p_+1) == '=') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::eq)); + } + else if (p_+1 < end_input_ && *(p_+1) == '~') + { + ++p_; + ++column_; + state_ = filter_states::expect_regex; + tokens_.push_back(token<JsonT>(token_types::regex)); + } + break; + case '>': + if (p_+1 < end_input_ && *(p_+1) == '=') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::gte)); + } + else + { + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::gt)); + } + break; + case '<': + if (p_+1 < end_input_ && *(p_+1) == '=') + { + ++p_; + ++column_; + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::lte)); + } + else + { + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::lt)); + } + break; + case '+': + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::plus)); + break; + case '-': + state_ = filter_states::expect_path_or_value; + tokens_.push_back(token<JsonT>(token_types::minus)); + break; + case ' ':case '\t': + break; + default: + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_); + break; + + } + ++p_; + ++column_; + break; + case filter_states::unquoted_text: + { + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '<': + case '>': + case '!': + case '=': + case '&': + case '|': + case '+': + case '-': + { + if (buffer_.length() > 0) + { + try + { + auto val = JsonT::parse(buffer_); + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val))); + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + buffer_.clear(); + } + state_ = filter_states::oper; + } + break; + case ')': + if (buffer_.length() > 0) + { + try + { + auto val = JsonT::parse(buffer_); + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val))); + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + buffer_.clear(); + } + tokens_.push_back(token<JsonT>(token_types::right_paren)); + if (--depth_ == 0) + { + state_ = filter_states::start; + done = true; + } + else + { + state_ = filter_states::expect_path_or_value; + } + ++p_; + ++column_; + break; + case ' ':case '\t': + if (buffer_.length() > 0) + { + try + { + auto val = JsonT::parse(buffer_); + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val))); + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + buffer_.clear(); + } + ++p_; + ++column_; + break; + default: + buffer_.push_back(*p_); + ++p_; + ++column_; + break; + } + } + break; + case filter_states::single_quoted_text: + { + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '\\': + buffer_.push_back(*p_); + if (p_+1 < end_input_) + { + ++p_; + ++column_; + buffer_.push_back(*p_); + } + break; + case '\'': + buffer_.push_back('\"'); + //if (buffer_.length() > 0) + { + try + { + auto val = JsonT::parse(buffer_); + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val))); + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + buffer_.clear(); + } + state_ = filter_states::expect_path_or_value; + break; + + default: + buffer_.push_back(*p_); + break; + } + } + ++p_; + ++column_; + break; + case filter_states::double_quoted_text: + { + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '\\': + buffer_.push_back(*p_); + if (p_+1 < end_input_) + { + ++p_; + ++column_; + buffer_.push_back(*p_); + } + break; + case '\"': + buffer_.push_back(*p_); + //if (buffer_.length() > 0) + { + try + { + auto val = JsonT::parse(buffer_); + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<value_term<JsonT>>(val))); + } + catch (const parse_exception& e) + { + throw parse_exception(e.code(),line_,column_); + } + buffer_.clear(); + } + state_ = filter_states::expect_path_or_value; + break; + + default: + buffer_.push_back(*p_); + break; + } + } + ++p_; + ++column_; + break; + case filter_states::expect_path_or_value: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '<': + case '>': + case '!': + case '=': + case '&': + case '|': + case '+': + case '-': + state_ = filter_states::oper; + // don't increment + break; + case '@': + buffer_.push_back(*p_); + state_ = filter_states::path; + ++p_; + ++column_; + break; + case ' ':case '\t': + ++p_; + ++column_; + break; + case '\'': + buffer_.push_back('\"'); + state_ = filter_states::single_quoted_text; + ++p_; + ++column_; + break; + case '\"': + buffer_.push_back(*p_); + state_ = filter_states::double_quoted_text; + ++p_; + ++column_; + break; + case '(': + ++depth_; + tokens_.push_back(token<JsonT>(token_types::left_paren)); + ++p_; + ++column_; + break; + case ')': + tokens_.push_back(token<JsonT>(token_types::right_paren)); + if (--depth_ == 0) + { + done = true; + state_ = filter_states::start; + } + ++p_; + ++column_; + break; + default: + // don't increment + state_ = filter_states::unquoted_text; + break; + }; + break; + case filter_states::expect_oper_or_right_round_bracket: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case ' ':case '\t': + break; + case ')': + tokens_.push_back(token<JsonT>(token_types::right_paren)); + if (--depth_ == 0) + { + done = true; + state_ = filter_states::start; + } + break; + case '<': + case '>': + case '!': + case '=': + case '&': + case '|': + case '+': + case '-': + { + state_ = filter_states::oper; + // don't increment p + } + break; + default: + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_); + break; + }; + break; + case filter_states::expect_right_round_bracket: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case ' ':case '\t': + break; + case ')': + tokens_.push_back(token<JsonT>(token_types::right_paren)); + if (--depth_ == 0) + { + done = true; + state_ = filter_states::start; + } + else + { + state_ = filter_states::expect_oper_or_right_round_bracket; + } + break; + default: + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter, jsonpath_error_category()),line_,column_); + break; + }; + ++p_; + ++column_; + break; + case filter_states::path: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '<': + case '>': + case '!': + case '=': + case '&': + case '|': + case '+': + case '-': + { + if (buffer_.length() > 0) + { + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<path_term<JsonT>>(buffer_))); + buffer_.clear(); + } + state_ = filter_states::oper; + // don't increment + } + break; + case ')': + if (buffer_.length() > 0) + { + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<path_term<JsonT>>(buffer_))); + tokens_.push_back(token<JsonT>(token_types::right_paren)); + buffer_.clear(); + } + if (--depth_ == 0) + { + state_ = filter_states::start; + done = true; + } + else + { + state_ = filter_states::expect_path_or_value; + } + ++p_; + ++column_; + break; + default: + buffer_.push_back(*p_); + ++p_; + ++column_; + break; + }; + break; + case filter_states::expect_regex: + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '/': + state_ = filter_states::regex; + break; + case ' ':case '\t': + break; + default: + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_expected_slash, jsonpath_error_category()),line_,column_); + break; + }; + ++p_; + ++column_; + break; + case filter_states::regex: + { + switch (*p_) + { + case '\r': + case '\n': + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case '/': + //if (buffer_.length() > 0) + { + std::regex::flag_type flags = std::regex_constants::ECMAScript; + if (p_+1 < end_input_ && *(p_+1) == 'i') + { + ++p_; + ++column_; + flags |= std::regex_constants::icase; + } + tokens_.push_back(token<JsonT>(token_types::term,std::make_shared<regex_term<JsonT>>(buffer_,flags))); + buffer_.clear(); + } + state_ = filter_states::expect_path_or_value; + break; + + default: + buffer_.push_back(*p_); + break; + } + } + ++p_; + ++column_; + break; + default: + ++p_; + ++column_; + break; + } + } + if (depth_ != 0) + { + throw parse_exception(std::error_code(jsonpath_parser_errc::invalid_filter_unbalanced_paren, jsonpath_error_category()),line_,column_); + } + } +}; + + +}} +#endif
\ No newline at end of file |