diff options
author | Manoj Srivastava <srivasta@debian.org> | 2020-05-23 00:33:19 -0700 |
---|---|---|
committer | Manoj Srivastava <srivasta@debian.org> | 2020-05-23 00:33:19 -0700 |
commit | d6b913d3ca2e84b75f3675fd6e9f5246c100cf27 (patch) | |
tree | 5fc28b7efc737bf2c79dc7d799e0a6013957fe11 /vendor/jsoncons-0.99.2/jsoncons_ext | |
parent | c42f029316c0c004a795ca170bdb50644a800534 (diff) | |
parent | 73a0259be1d44fdb2ab34266ae0ff63f0d8f0b60 (diff) |
Merge branch 'master' into dgit/siddebian/2.4.0-ah-1archive/debian/2.4.0-ah-1
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons_ext')
9 files changed, 4469 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp new file mode 100644 index 00000000..59936cd7 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp @@ -0,0 +1,59 @@ +// 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_EXT_TYPE_EXTENSIONS_HPP +#define JSONCONS_EXT_TYPE_EXTENSIONS_HPP + +#include "jsoncons/json.hpp" +#include "boost/date_time/gregorian/gregorian.hpp" + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +namespace jsoncons +{ + template <typename JsonT> + class json_type_traits<JsonT,boost::gregorian::date> + { + public: + static bool is(const JsonT& val) JSONCONS_NOEXCEPT + { + if (!val.is_string()) + { + return false; + } + std::string s = val.template as<std::string>(); + try + { + boost::gregorian::date_from_iso_string(s); + return true; + } + catch (...) + { + return false; + } + } + + static boost::gregorian::date as(const JsonT& val) + { + std::string s = val.template as<std::string>(); + return boost::gregorian::from_simple_string(s); + } + + static void assign(JsonT& lhs, boost::gregorian::date val) + { + lhs = to_iso_extended_string(val); + } + }; +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp new file mode 100644 index 00000000..5056d380 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp @@ -0,0 +1,55 @@ +/// 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_CSV_CSV_TEXT_ERROR_CATEGORY_HPP +#define JSONCONS_CSV_CSV_TEXT_ERROR_CATEGORY_HPP + +#include "jsoncons/jsoncons.hpp" +#include <system_error> + +namespace jsoncons { namespace csv { + +namespace csv_parser_errc +{ + const int unexpected_eof = 1; + const int expected_quote = 2; + const int invalid_csv_text = 3; + const int invalid_state = 4; +} + +class csv_error_category_impl + : public std::error_category +{ +public: + virtual const char* name() const JSONCONS_NOEXCEPT + { + return "csv"; + } + virtual std::string message(int ev) const + { + switch (ev) + { + case csv_parser_errc::unexpected_eof: + return "Unexpected end of file"; + case csv_parser_errc::expected_quote: + return "Expected quote character"; + case csv_parser_errc::invalid_csv_text: + return "Invalid CSV text"; + default: + return "Unknown JSON parser error"; + } + } +}; + +inline +const std::error_category& csv_error_category() +{ + static csv_error_category_impl instance; + return instance; +} + +}} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp new file mode 100644 index 00000000..099a154f --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp @@ -0,0 +1,341 @@ +// 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_CSV_CSV_PARAMETERS_HPP +#define JSONCONS_CSV_CSV_PARAMETERS_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <ostream> +#include <cstdlib> +#include <limits> +#include <cwchar> + +namespace jsoncons { namespace csv { + +enum class quote_styles +{ + all,minimal,none,nonnumeric +}; + +template <typename CharT> +class basic_csv_parameters +{ +public: + static const size_t default_indent = 4; + +// Constructors + + basic_csv_parameters() + : + assume_header_(false), + ignore_empty_values_(false), + trim_leading_(false), + trim_trailing_(false), + trim_leading_inside_quotes_(false), + trim_trailing_inside_quotes_(false), + unquoted_empty_value_is_null_(false), + field_delimiter_(','), + quote_char_('\"'), + quote_escape_char_('\"'), + comment_starter_('\0'), + quote_style_(quote_styles::minimal), + max_lines_(std::numeric_limits<unsigned long>::max JSONCONS_NO_MACRO_EXP()), + header_lines_(0) + { + line_delimiter_.push_back('\n'); + } + +// Properties + + size_t header_lines() const + { + return (assume_header_ && header_lines_ <= 1) ? 1 : header_lines_; + } + + basic_csv_parameters<CharT>& header_lines(size_t value) + { + header_lines_ = value; + return *this; + } + + bool assume_header() const + { + return assume_header_; + } + + basic_csv_parameters<CharT>& assume_header(bool value) + { + assume_header_ = value; + return *this; + } + + bool ignore_empty_values() const + { + return ignore_empty_values_; + } + + basic_csv_parameters<CharT>& ignore_empty_values(bool value) + { + ignore_empty_values_ = value; + return *this; + } + + bool trim_leading() const + { + return trim_leading_; + } + + basic_csv_parameters<CharT>& trim_leading(bool value) + { + trim_leading_ = value; + return *this; + } + + bool trim_trailing() const + { + return trim_trailing_; + } + + basic_csv_parameters<CharT>& trim_trailing(bool value) + { + trim_trailing_ = value; + return *this; + } + + bool trim_leading_inside_quotes() const + { + return trim_leading_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_leading_inside_quotes(bool value) + { + trim_leading_inside_quotes_ = value; + return *this; + } + + bool trim_trailing_inside_quotes() const + { + return trim_trailing_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_trailing_inside_quotes(bool value) + { + trim_trailing_inside_quotes_ = value; + return *this; + } + + bool trim() const + { + return trim_leading_ && trim_trailing_; + } + + basic_csv_parameters<CharT>& trim(bool value) + { + trim_leading_ = value; + trim_trailing_ = value; + return *this; + } + + bool trim_inside_quotes() const + { + return trim_leading_inside_quotes_ && trim_trailing_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_inside_quotes(bool value) + { + trim_leading_inside_quotes_ = value; + trim_trailing_inside_quotes_ = value; + return *this; + } + + bool unquoted_empty_value_is_null() const + { + return unquoted_empty_value_is_null_; + } + + basic_csv_parameters<CharT>& unquoted_empty_value_is_null(bool value) + { + unquoted_empty_value_is_null_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_names() const + { + return column_names_; + } + + basic_csv_parameters<CharT>& column_names(const std::vector<std::basic_string<CharT>>& value) + { + column_names_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_types() const + { + return column_types_; + } + + basic_csv_parameters<CharT>& column_types(const std::vector<std::basic_string<CharT>>& value) + { + column_types_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_defaults() const + { + return column_defaults_; + } + + basic_csv_parameters<CharT>& column_defaults(const std::vector<std::basic_string<CharT>>& value) + { + column_defaults_ = value; + return *this; + } + + CharT field_delimiter() const + { + return field_delimiter_; + } + + basic_csv_parameters<CharT>& field_delimiter(CharT value) + { + field_delimiter_ = value; + return *this; + } + + std::basic_string<CharT> line_delimiter() const + { + return line_delimiter_; + } + + basic_csv_parameters<CharT>& line_delimiter(std::basic_string<CharT> value) + { + line_delimiter_ = value; + return *this; + } + + CharT quote_char() const + { + return quote_char_; + } + + basic_csv_parameters<CharT>& quote_char(CharT value) + { + quote_char_ = value; + return *this; + } + + CharT quote_escape_char() const + { + return quote_escape_char_; + } + + basic_csv_parameters<CharT>& quote_escape_char(CharT value) + { + quote_escape_char_ = value; + return *this; + } + + CharT comment_starter() const + { + return comment_starter_; + } + + basic_csv_parameters<CharT>& comment_starter(CharT value) + { + comment_starter_ = value; + return *this; + } + + quote_styles quote_style() const + { + return quote_style_; + } + + basic_csv_parameters<CharT>& assume_header(quote_styles value) + { + quote_style_ = value; + return *this; + } + + unsigned long max_lines() const + { + return max_lines_; + } + + basic_csv_parameters<CharT>& max_lines(unsigned long value) + { + max_lines_ = value; + return *this; + } + +#if !defined(JSONCONS_NO_DEPRECATED) + + std::basic_string<CharT> header() const + { + return header_; + } + + basic_csv_parameters<CharT>& header(const std::basic_string<CharT>& value) + { + header_ = value; + return *this; + } + + std::basic_string<CharT> data_types() const + { + return data_types_; + } + + basic_csv_parameters<CharT>& data_types(const std::basic_string<CharT>& value) + { + data_types_ = value; + return *this; + } + + std::basic_string<CharT> default_values() const + { + return default_values_; + } + + basic_csv_parameters<CharT>& default_values(const std::basic_string<CharT>& value) + { + default_values_ = value; + return *this; + } +#endif +private: + bool assume_header_; + bool ignore_empty_values_; + bool trim_leading_; + bool trim_trailing_; + bool trim_leading_inside_quotes_; + bool trim_trailing_inside_quotes_; + bool unquoted_empty_value_is_null_; + CharT field_delimiter_; + CharT quote_char_; + CharT quote_escape_char_; + CharT comment_starter_; + quote_styles quote_style_; + unsigned long max_lines_; + size_t header_lines_; + std::basic_string<CharT> line_delimiter_; + std::basic_string<CharT> header_; + std::basic_string<CharT> data_types_; + std::basic_string<CharT> default_values_; + std::vector<std::basic_string<CharT>> column_names_; + std::vector<std::basic_string<CharT>> column_types_; + std::vector<std::basic_string<CharT>> column_defaults_; +}; + +typedef basic_csv_parameters<char> csv_parameters; +typedef basic_csv_parameters<wchar_t> wcsv_parameters; + +}} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp new file mode 100644 index 00000000..14323666 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp @@ -0,0 +1,903 @@ +// Copyright 2015 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_CSV_CSV_PARSER_HPP +#define JSONCONS_CSV_CSV_PARSER_HPP + +#include <memory> +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <stdexcept> +#include <system_error> +#include <cctype> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons/json_parser.hpp" +#include "jsoncons/json_filter.hpp" +#include "jsoncons_ext/csv/csv_error_category.hpp" +#include "jsoncons_ext/csv/csv_parameters.hpp" + +namespace jsoncons { namespace csv { + +template <typename CharT> +struct json_csv_parser_traits +{ +}; + +template <> +struct json_csv_parser_traits<char> +{ + static const std::string string_literal() {return "string";}; + + static const std::string integer_literal() {return "integer";}; + + static const std::string float_literal() {return "float";}; + + static const std::string boolean_literal() {return "boolean";}; +}; + +template <> +struct json_csv_parser_traits<wchar_t> // assume utf16 +{ + static const std::wstring string_literal() {return L"string";}; + + static const std::wstring integer_literal() {return L"integer";}; + + static const std::wstring float_literal() {return L"float";}; + + static const std::wstring boolean_literal() {return L"boolean";}; +}; + +enum class csv_modes { + done, + header, + array, + object +}; + +enum class csv_states +{ + start, + comment, + expect_value, + between_fields, + quoted_string, + unquoted_string, + escaped_value, + minus, + zero, + integer, + fraction, + exp1, + exp2, + exp3, + done +}; + +enum class data_types +{ + string_t,integer_t,float_t,boolean_t +}; + +template<typename CharT> +class basic_csv_parser : private basic_parsing_context<CharT> +{ + static const int default_depth = 3; + + csv_states state_; + int top_; + std::vector<csv_modes> stack_; + basic_json_input_handler<CharT> *handler_; + basic_parse_error_handler<CharT> *err_handler_; + bool is_negative_; + uint32_t cp_; + size_t index_; + unsigned long column_; + unsigned long line_; + int curr_char_; + int prev_char_; + std::basic_string<CharT> string_buffer_; + csv_states saved_state_; + int depth_; + basic_csv_parameters<CharT> parameters_; + std::vector<std::basic_string<CharT>> column_names_; + std::vector<data_types> column_types_; + std::vector<std::basic_string<CharT>> column_defaults_; + size_t column_index_; + basic_begin_end_json_filter<CharT> filter_; + basic_json_parser<CharT> parser_; + +public: + basic_csv_parser(basic_json_input_handler<CharT>& handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())), + is_negative_(false), + cp_(0), + index_(0), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_csv_parameters<CharT> params) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())), + is_negative_(false), + cp_(0), + index_(0), + parameters_(params), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + is_negative_(false), + cp_(0), + index_(0), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler, + basic_csv_parameters<CharT> params) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + is_negative_(false), + cp_(0), + index_(0), + parameters_(params), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + ~basic_csv_parser() + { + } + + const basic_parsing_context<CharT>& parsing_context() const + { + return *this; + } + + bool done() const + { + return state_ == csv_states::done; + } + + const std::vector<std::basic_string<CharT>>& column_labels() const + { + return column_names_; + } + + void after_field() + { + ++column_index_; + } + + void before_record() + { + if (column_index_ == 0) + { + switch (stack_[top_]) + { + case csv_modes::array: + handler_->begin_array(*this); + break; + case csv_modes::object: + handler_->begin_object(*this); + break; + default: + break; + } + } + } + + void after_record() + { + switch (stack_[top_]) + { + case csv_modes::array: + handler_->end_array(*this); + break; + case csv_modes::object: + handler_->end_object(*this); + break; + case csv_modes::header: + if (line_ >= parameters_.header_lines()) + { + if (column_names_.size() > 0) + { + flip(csv_modes::header, csv_modes::object); + } + else + { + flip(csv_modes::header, csv_modes::array); + } + } + break; + default: + break; + } + column_index_ = 0; + } + + void begin_parse() + { + push(csv_modes::done); + handler_->begin_json(); + + if (parameters_.column_names().size() > 0) + { + column_names_ = parameters_.column_names(); + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.header().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.quote_char(parameters_.quote_char()); + params.quote_escape_char(parameters_.quote_escape_char()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.header().data(),0,parameters_.header().length()); + p.end_parse(); + column_names_ = p.column_labels(); + } +#endif + if (parameters_.column_types().size() > 0) + { + column_types_.resize(parameters_.column_types().size()); + for (size_t i = 0; i < parameters_.column_types().size(); ++i) + { + if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::string_literal()) + { + column_types_[i] = data_types::string_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::integer_literal()) + { + column_types_[i] = data_types::integer_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::float_literal()) + { + column_types_[i] = data_types::float_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::boolean_literal()) + { + column_types_[i] = data_types::boolean_t; + } + } + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.data_types().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.data_types().data(),0,parameters_.data_types().length()); + p.end_parse(); + column_types_.resize(p.column_labels().size()); + for (size_t i = 0; i < p.column_labels().size(); ++i) + { + if (p.column_labels()[i] == json_csv_parser_traits<CharT>::string_literal()) + { + column_types_[i] = data_types::string_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::integer_literal()) + { + column_types_[i] = data_types::integer_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::float_literal()) + { + column_types_[i] = data_types::float_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::boolean_literal()) + { + column_types_[i] = data_types::boolean_t; + } + } + } +#endif + if (parameters_.column_defaults().size() > 0) + { + column_defaults_ = parameters_.column_defaults(); + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.default_values().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.default_values().data(),0,parameters_.default_values().length()); + p.end_parse(); + column_defaults_.resize(p.column_labels().size()); + for (size_t i = 0; i < p.column_labels().size(); ++i) + { + column_defaults_[i] = p.column_labels()[i]; + } + } +#endif + if (parameters_.header_lines() > 0) + { + push(csv_modes::header); + } + else + { + push(csv_modes::array); + } + handler_->begin_array(*this); + state_ = csv_states::expect_value; + column_index_ = 0; + prev_char_ = 0; + curr_char_ = 0; + column_ = 1; + } + + void parse(const CharT* p, size_t start, size_t length) + { + index_ = start; + for (; index_ < length && state_ != csv_states::done; ++index_) + { + curr_char_ = p[index_]; +all_csv_states: + switch (state_) + { + case csv_states::comment: + if (curr_char_ == '\n') + { + state_ = csv_states::expect_value; + } + else if (prev_char_ == '\r') + { + state_ = csv_states::expect_value; + goto all_csv_states; + } + break; + case csv_states::expect_value: + if (column_ == 1 && curr_char_ == parameters_.comment_starter()) + { + state_ = csv_states::comment; + } + else + { + state_ = csv_states::unquoted_string; + goto all_csv_states; + } + break; + case csv_states::between_fields: + if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n')) + { + after_record(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == parameters_.field_delimiter()) + { + state_ = csv_states::expect_value; + } + break; + case csv_states::escaped_value: + { + if (curr_char_ == parameters_.quote_char()) + { + string_buffer_.push_back(curr_char_); + state_ = csv_states::quoted_string; + } + else if (parameters_.quote_escape_char() == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + state_ = csv_states::between_fields; + goto all_csv_states; + } + } + break; + case csv_states::quoted_string: + { + if (curr_char_ == parameters_.quote_escape_char()) + { + state_ = csv_states::escaped_value; + } + else if (curr_char_ == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + state_ = csv_states::between_fields; + } + else + { + string_buffer_.push_back(curr_char_); + } + } + break; + case csv_states::unquoted_string: + { + if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n')) + { + before_record(); + end_unquoted_string_value(); + after_field(); + after_record(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == '\n') + { + if (prev_char_ != '\r') + { + before_record(); + end_unquoted_string_value(); + after_field(); + after_record(); + state_ = csv_states::expect_value; + } + } + else if (curr_char_ == parameters_.field_delimiter()) + { + before_record(); + end_unquoted_string_value(); + after_field(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == parameters_.quote_char()) + { + string_buffer_.clear(); + state_ = csv_states::quoted_string; + } + else + { + string_buffer_.push_back(curr_char_); + } + } + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_state, csv_error_category()), *this); + break; + } + if (line_ > parameters_.max_lines()) + { + state_ = csv_states::done; + } + switch (curr_char_) + { + case '\r': + ++line_; + column_ = 1; + break; + case '\n': + if (prev_char_ != '\r') + { + ++line_; + } + column_ = 1; + break; + default: + ++column_; + break; + } + prev_char_ = curr_char_; + } + } + + void end_parse() + { + switch (state_) + { + case csv_states::unquoted_string: + before_record(); + end_unquoted_string_value(); + after_field(); + break; + case csv_states::escaped_value: + if (parameters_.quote_escape_char() == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + } + break; + default: + break; + } + if (column_index_ > 0) + { + after_record(); + } + switch (stack_[top_]) + { + case csv_modes::array: + if (!pop(csv_modes::array)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + case csv_modes::object: + if (!pop(csv_modes::object)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + case csv_modes::header: + if (!pop(csv_modes::header)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + default: + break; + } + handler_->end_array(*this); + if (!pop(csv_modes::done)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + handler_->end_json(); + } + + csv_states state() const + { + return state_; + } + + size_t index() const + { + return index_; + } +private: + + void trim_string_buffer(bool trim_leading, bool trim_trailing) + { + size_t start = 0; + size_t length = string_buffer_.length(); + if (trim_leading) + { + bool done = false; + while (!done && start < string_buffer_.length()) + { + if ((string_buffer_[start] < 256) && std::isspace(string_buffer_[start])) + { + ++start; + } + else + { + done = true; + } + } + } + if (trim_trailing) + { + bool done = false; + while (!done && length > 0) + { + if ((string_buffer_[length-1] < 256) && std::isspace(string_buffer_[length-1])) + { + --length; + } + else + { + done = true; + } + } + } + if (start != 0 || length != string_buffer_.size()) + { + string_buffer_ = string_buffer_.substr(start,length-start); + } + } + + void end_unquoted_string_value() + { + if (parameters_.trim_leading() | parameters_.trim_trailing()) + { + trim_string_buffer(parameters_.trim_leading(),parameters_.trim_trailing()); + } + switch (stack_[top_]) + { + case csv_modes::header: + if (parameters_.assume_header() && line_ == 1) + { + column_names_.push_back(string_buffer_); + } + break; + case csv_modes::object: + if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0)) + { + if (column_index_ < column_names_.size()) + { + handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this); + if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0) + { + handler_->value(jsoncons::null_type(),*this); + } + else + { + end_value(); + } + } + } + break; + case csv_modes::array: + if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0) + { + handler_->value(jsoncons::null_type(),*this); + } + else + { + end_value(); + } + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this); + break; + } + state_ = csv_states::expect_value; + string_buffer_.clear(); + } + + void end_quoted_string_value() + { + if (parameters_.trim_leading_inside_quotes() | parameters_.trim_trailing_inside_quotes()) + { + trim_string_buffer(parameters_.trim_leading_inside_quotes(),parameters_.trim_trailing_inside_quotes()); + } + switch (stack_[top_]) + { + case csv_modes::header: + if (parameters_.assume_header() && line_ == 1) + { + column_names_.push_back(string_buffer_); + } + break; + case csv_modes::object: + if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0)) + { + if (column_index_ < column_names_.size()) + { + handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this); + end_value(); + } + } + break; + case csv_modes::array: + end_value(); + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this); + break; + } + state_ = csv_states::expect_value; + string_buffer_.clear(); + } + + void end_value() + { + if (column_index_ < column_types_.size()) + { + switch (column_types_[column_index_]) + { + case data_types::integer_t: + { + std::istringstream iss(string_buffer_); + long long val; + iss >> val; + if (!iss.fail()) + { + handler_->value(val, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + case data_types::float_t: + { + std::istringstream iss(string_buffer_); + double val; + iss >> val; + if (!iss.fail()) + { + handler_->value(val, 0, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + case data_types::boolean_t: + { + if (string_buffer_.length() == 1 && string_buffer_[0] == '0') + { + handler_->value(false, *this); + } + else if (string_buffer_.length() == 1 && string_buffer_[0] == '1') + { + handler_->value(true, *this); + } + else if (string_buffer_.length() == 5 && ((string_buffer_[0] == 'f' || string_buffer_[0] == 'F') && (string_buffer_[1] == 'a' || string_buffer_[1] == 'A') && (string_buffer_[2] == 'l' || string_buffer_[2] == 'L') && (string_buffer_[3] == 's' || string_buffer_[3] == 'S') && (string_buffer_[4] == 'e' || string_buffer_[4] == 'E'))) + { + handler_->value(false, *this); + } + else if (string_buffer_.length() == 4 && ((string_buffer_[0] == 't' || string_buffer_[0] == 'T') && (string_buffer_[1] == 'r' || string_buffer_[1] == 'R') && (string_buffer_[2] == 'u' || string_buffer_[2] == 'U') && (string_buffer_[3] == 'e' || string_buffer_[3] == 'E'))) + { + handler_->value(true, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + default: + if (string_buffer_.length() > 0) + { + handler_->value(string_buffer_.data(), string_buffer_.length(), *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value("", *this); + } + } + break; + } + } + else + { + handler_->value(string_buffer_.data(), string_buffer_.length(), *this); + } + } + + size_t do_line_number() const override + { + return line_; + } + + size_t do_column_number() const override + { + return column_; + } + + CharT do_current_char() const override + { + return (CharT)prev_char_; + } + + void push(csv_modes mode) + { + ++top_; + if (top_ >= depth_) + { + depth_ *= 2; + stack_.resize(depth_); + } + stack_[top_] = mode; + } + + int peek() + { + return stack_[top_]; + } + + bool peek(csv_modes mode) + { + return stack_[top_] == mode; + } + + bool flip(csv_modes mode1, csv_modes mode2) + { + if (top_ < 0 || stack_[top_] != mode1) + { + return false; + } + stack_[top_] = mode2; + return true; + } + + bool pop(csv_modes mode) + { + if (top_ < 0 || stack_[top_] != mode) + { + return false; + } + --top_; + return true; + } +}; + +typedef basic_csv_parser<char> csv_parser; +typedef basic_csv_parser<wchar_t> wcsv_parser; + +}} + +#endif + diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp new file mode 100644 index 00000000..38213e25 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp @@ -0,0 +1,175 @@ +// 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_CSV_CSV_READER_HPP +#define JSONCONS_CSV_CSV_READER_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <stdexcept> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons_ext/csv/csv_error_category.hpp" +#include "jsoncons_ext/csv/csv_parser.hpp" +#include "jsoncons/json.hpp" + +namespace jsoncons { namespace csv { + +template<typename CharT> +class basic_csv_reader +{ + struct stack_item + { + stack_item() + : array_begun_(false) + { + } + + bool array_begun_; + }; +public: + // Structural characters + static const size_t default_max_buffer_length = 16384; + //! Parse an input stream of CSV text into a json object + /*! + \param is The input stream to read from + */ + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler) + + : parser_(handler), + is_(std::addressof(is)), + buffer_(default_max_buffer_length), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_csv_parameters<CharT> params) + + : parser_(handler,params), + is_(std::addressof(is)), + buffer_(default_max_buffer_length), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler) + : + parser_(handler,err_handler), + is_(std::addressof(is)), + buffer_(), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + + + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler, + basic_csv_parameters<CharT> params) + : + parser_(handler,err_handler,params), + is_(std::addressof(is)), + buffer_(), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + ~basic_csv_reader() + { + } + + void read() + { + parser_.begin_parse(); + while (!eof_ && !parser_.done()) + { + if (!(index_ < buffer_length_)) + { + if (!is_->eof()) + { + is_->read(buffer_.data(), buffer_capacity_); + buffer_length_ = static_cast<size_t>(is_->gcount()); + if (buffer_length_ == 0) + { + eof_ = true; + } + index_ = 0; + } + else + { + eof_ = true; + } + } + if (!eof_) + { + parser_.parse(buffer_.data(),index_,buffer_length_); + index_ = parser_.index(); + } + } + parser_.end_parse(); + } + + bool eof() const + { + return eof_; + } + + size_t buffer_capacity() const + { + return buffer_capacity_; + } + + void buffer_capacity(size_t buffer_capacity) + { + buffer_capacity_ = buffer_capacity; + } + +private: + basic_csv_reader(const basic_csv_reader&) = delete; + basic_csv_reader& operator = (const basic_csv_reader&) = delete; + + basic_csv_parser<CharT> parser_; + std::basic_istream<CharT>* is_; + std::vector<CharT> buffer_; + size_t buffer_capacity_; + size_t buffer_position_; + size_t buffer_length_; + bool eof_; + size_t index_; +}; + +typedef basic_csv_reader<char> csv_reader; + +}} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp new file mode 100644 index 00000000..f331b629 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp @@ -0,0 +1,445 @@ +// 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_CSV_CSV_SERIALIZER_HPP +#define JSONCONS_CSV_CSV_SERIALIZER_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <ostream> +#include <cstdlib> +#include <map> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/output_format.hpp" +#include "jsoncons/json_output_handler.hpp" +#include <limits> // std::numeric_limits + +namespace jsoncons { namespace csv { + +template <typename CharT> +struct csv_char_traits +{ +}; + +template <> +struct csv_char_traits<char> +{ + static const std::string all_literal() {return "all";}; + + static const std::string minimal_literal() {return "minimal";}; + + static const std::string none_literal() {return "none";}; + + static const std::string nonnumeric_literal() {return "nonumeric";}; +}; + +template <> +struct csv_char_traits<wchar_t> +{ + static const std::wstring all_literal() {return L"all";}; + + static const std::wstring minimal_literal() {return L"minimal";}; + + static const std::wstring none_literal() {return L"none";}; + + static const std::wstring nonnumeric_literal() {return L"nonumeric";}; +}; + +template <typename CharT> +void escape_string(const CharT* s, + size_t length, + CharT quote_char, CharT quote_escape_char, + buffered_ostream<CharT>& os) +{ + const CharT* begin = s; + const CharT* end = s + length; + for (const CharT* it = begin; it != end; ++it) + { + CharT c = *it; + if (c == quote_char) + { + os.put(quote_escape_char); + os.put(quote_char); + } + else + { + os.put(c); + } + } +} + +template<typename CharT> +class basic_csv_serializer : public basic_json_output_handler<CharT> +{ + struct stack_item + { + stack_item(bool is_object) + : is_object_(is_object), count_(0), skip_(false) + { + } + bool is_object() const + { + return is_object_; + } + + bool is_object_; + size_t count_; + bool skip_; + }; + buffered_ostream<CharT> os_; + basic_csv_parameters<CharT> parameters_; + basic_output_format<CharT> format_; + std::vector<stack_item> stack_; + std::streamsize original_precision_; + std::ios_base::fmtflags original_format_flags_; + std::basic_ostringstream<CharT> header_oss_; + buffered_ostream<CharT> header_os_; + std::map<std::basic_string<CharT>,size_t> header_; + float_printer<CharT> fp_; +public: + basic_csv_serializer(std::basic_ostream<CharT>& os) + : + os_(os), + format_(), + stack_(), + original_precision_(), + original_format_flags_(), + header_os_(header_oss_), + header_(), + fp_(format_.precision()) + { + } + + basic_csv_serializer(std::basic_ostream<CharT>& os, + basic_csv_parameters<CharT> params) + : + os_(os), + parameters_(params), + format_(), + stack_(), + original_precision_(), + original_format_flags_(), + header_os_(header_oss_), + header_(), + fp_(format_.precision()) + { + } + + ~basic_csv_serializer() + { + } + +private: + + void do_begin_json() override + { + } + + void do_end_json() override + { + } + + void do_begin_object() override + { + stack_.push_back(stack_item(true)); + } + + void do_end_object() override + { + if (stack_.size() == 2) + { + os_.write(parameters_.line_delimiter()); + if (stack_[0].count_ == 0) + { + os_.write(header_oss_.str()); + os_.write(parameters_.line_delimiter()); + } + } + stack_.pop_back(); + + end_value(); + } + + void do_begin_array() override + { + stack_.push_back(stack_item(false)); + } + + void do_end_array() override + { + if (stack_.size() == 2) + { + os_.write(parameters_.line_delimiter()); + } + stack_.pop_back(); + + end_value(); + } + + void do_name(const CharT* name, size_t length) override + { + if (stack_.size() == 2) + { + if (stack_[0].count_ == 0) + { + if (stack_.back().count_ > 0) + { + os_.put(parameters_.field_delimiter()); + } + bool quote = false; + if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric || + (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(name,length,parameters_.field_delimiter()) != nullptr)) + { + quote = true; + os_.put(parameters_.quote_char()); + } + jsoncons::csv::escape_string<CharT>(name, length, parameters_.quote_char(), parameters_.quote_escape_char(), os_); + if (quote) + { + os_.put(parameters_.quote_char()); + } + header_[name] = stack_.back().count_; + } + else + { + typename std::map<std::basic_string<CharT>,size_t>::iterator it = header_.find(std::basic_string<CharT>(name,length)); + if (it == header_.end()) + { + stack_.back().skip_ = true; + //std::cout << " Not found "; + } + else + { + stack_.back().skip_ = false; + while (stack_.back().count_ < it->second) + { + os_.put(parameters_.field_delimiter()); + ++stack_.back().count_; + } + // std::cout << " (" << it->value() << " " << stack_.back().count_ << ") "; + } + } + } + } + + void do_null_value() override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + do_null_value(header_os_); + } + else + { + do_null_value(os_); + } + } + } + + void do_string_value(const CharT* val, size_t length) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,length,header_os_); + } + else + { + value(val,length,os_); + } + } + } + + void do_double_value(double val, uint8_t precision) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_integer_value(int64_t val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_uinteger_value(uint64_t val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_bool_value(bool val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void value(const CharT* val, size_t length, buffered_ostream<CharT>& os) + { + begin_value(os); + + bool quote = false; + if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric || + (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(val, length, parameters_.field_delimiter()) != nullptr)) + { + quote = true; + os.put(parameters_.quote_char()); + } + jsoncons::csv::escape_string<CharT>(val, length, parameters_.quote_char(), parameters_.quote_escape_char(), os); + if (quote) + { + os.put(parameters_.quote_char()); + } + + end_value(); + } + + void value(double val, buffered_ostream<CharT>& os) + { + begin_value(os); + + if (is_nan(val) && format_.replace_nan()) + { + os.write(format_.nan_replacement()); + } + else if (is_pos_inf(val) && format_.replace_pos_inf()) + { + os.write(format_.pos_inf_replacement()); + } + else if (is_neg_inf(val) && format_.replace_neg_inf()) + { + os.write(format_.neg_inf_replacement()); + } + //else if (format_.floatfield() != 0) + //{ + // std::basic_ostringstream<CharT> ss; + // ss.imbue(std::locale::classic()); + // ss.setf(format_.floatfield(), std::ios::floatfield); + // ss << std::showpoint << std::setprecision(format_.precision()) << val; + // os.write(ss.str()); + //} + else + { + fp_.print(val,format_.precision(),os); + } + + end_value(); + + } + + void value(int64_t val, buffered_ostream<CharT>& os) + { + begin_value(os); + + std::basic_ostringstream<CharT> ss; + ss << val; + os.write(ss.str()); + + end_value(); + } + + void value(uint64_t val, buffered_ostream<CharT>& os) + { + begin_value(os); + + std::basic_ostringstream<CharT> ss; + ss << val; + os.write(ss.str()); + + end_value(); + } + + void value(bool val, buffered_ostream<CharT>& os) + { + begin_value(os); + + if (val) + { + auto buf = json_literals<CharT>::true_literal(); + os.write(buf.first,buf.second); + } + else + { + auto buf = json_literals<CharT>::false_literal(); + os.write(buf.first,buf.second); + } + + end_value(); + } + + void do_null_value(buffered_ostream<CharT>& os) + { + begin_value(os); + auto buf = json_literals<CharT>::null_literal(); + os.write(buf.first,buf.second); + end_value(); + + } + + void begin_value(buffered_ostream<CharT>& os) + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + os.put(parameters_.field_delimiter()); + } + } + } + + void end_value() + { + if (!stack_.empty()) + { + ++stack_.back().count_; + } + } +}; + +typedef basic_csv_serializer<char> csv_serializer; + +}} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp new file mode 100644 index 00000000..7e530abd --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp @@ -0,0 +1,921 @@ +// 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_JSONQUERY_HPP +#define JSONCONS_JSONPATH_JSONQUERY_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <memory> +#include "jsoncons/json.hpp" +#include "jsonpath_filter.hpp" +#include "jsonpath_error_category.hpp" + +namespace jsoncons { namespace jsonpath { + + template<typename CharT> + bool try_string_to_index(const CharT *s, size_t length, size_t* value) + { + static const size_t max_value = std::numeric_limits<size_t>::max JSONCONS_NO_MACRO_EXP(); + static const size_t max_value_div_10 = max_value / 10; + + size_t n = 0; + for (size_t i = 0; i < length; ++i) + { + CharT c = s[i]; + switch (c) + { + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + { + size_t x = c - '0'; + if (n > max_value_div_10) + { + return false; + } + n = n * 10; + if (n > max_value - x) + { + return false; + } + + n += x; + } + break; + default: + return false; + break; + } + } + *value = n; + return true; + } + + template <typename CharT> + struct json_jsonpath_traits + { + }; + + template <> + struct json_jsonpath_traits<char> + { + static const std::string length_literal() {return "length";}; + }; + + template <> + struct json_jsonpath_traits<wchar_t> // assume utf16 + { + static const std::wstring length_literal() {return L"length";}; + }; + +// here + +template<class JsonT> +JsonT json_query(const JsonT& root, const typename JsonT::char_type* path, size_t length) +{ + jsonpath_evaluator<JsonT> evaluator; + evaluator.evaluate(root,path,length); + return evaluator.get_values(); +} + +template<class JsonT> +JsonT json_query(const JsonT& root, const typename JsonT::string_type& path) +{ + return json_query(root,path.data(),path.length()); +} + +template<class JsonT> +JsonT json_query(const JsonT& root, const typename JsonT::char_type* path) +{ + return json_query(root,path,std::char_traits<typename JsonT::char_type>::length(path)); +} + +enum class states +{ + start, + cr, + lf, + expect_separator, + expect_unquoted_name, + unquoted_name, + single_quoted_name, + double_quoted_name, + left_bracket, + left_bracket_start, + left_bracket_end, + left_bracket_end2, + left_bracket_step, + left_bracket_step2, + expect_right_bracket, + dot +}; + +template<class JsonT> +class jsonpath_evaluator : private basic_parsing_context<typename JsonT::char_type> +{ +private: + typedef typename JsonT::char_type char_type; + typedef typename JsonT::string_type string_type; + typedef const JsonT* cjson_ptr; + typedef std::vector<cjson_ptr> node_set; + + basic_parse_error_handler<char_type> *err_handler_; + states state_; + string_type buffer_; + size_t start_; + size_t end_; + size_t step_; + bool positive_start_; + bool positive_end_; + bool positive_step_; + bool end_undefined_; + std::vector<node_set> stack_; + bool recursive_descent_; + std::vector<cjson_ptr> nodes_; + std::vector<std::shared_ptr<JsonT>> temp_; + size_t line_; + size_t column_; + const char_type* begin_input_; + const char_type* end_input_; + const char_type* p_; + states pre_line_break_state_; + + void transfer_nodes() + { + stack_.push_back(nodes_); + nodes_.clear(); + } + +public: + jsonpath_evaluator() + : err_handler_(std::addressof(basic_default_parse_error_handler<char_type>::instance())) + { + } + + JsonT get_values() const + { + JsonT result = JsonT::make_array(); + + if (stack_.size() > 0) + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + cjson_ptr p = stack_.back()[i]; + result.add(*p); + } + } + return result; + } + + void evaluate(const JsonT& root, const string_type& path) + { + evaluate(root,path.data(),path.length()); + } + void evaluate(const JsonT& root, const char_type* path) + { + evaluate(root,path,std::char_traits<char_type>::length(path)); + } + + void evaluate(const JsonT& root, const char_type* path, size_t length) + { + begin_input_ = path; + end_input_ = path + length; + p_ = begin_input_; + + line_ = 1; + column_ = 1; + state_ = states::start; + buffer_.clear(); + start_ = 0; + end_ = 0; + step_ = 1; + recursive_descent_ = false; + positive_start_ = true; + positive_end_ = true; + positive_step_ = true; + end_undefined_ = false; + + while (p_ < end_input_) + { + switch (state_) + { + case 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 states::lf: + ++line_; + column_ = 1; + state_ = pre_line_break_state_; + break; + case states::start: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ' ':case '\t': + ++p_; + ++column_; + break; + case '$': + case '@': + { + node_set v; + v.push_back(std::addressof(root)); + stack_.push_back(v); + state_ = states::expect_separator; + } + break; + default: + err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_root, jsonpath_error_category()), *this); + break; + }; + ++p_; + ++column_; + break; + case states::dot: + switch (*p_) + { + case '.': + recursive_descent_ = true; + ++p_; + ++column_; + state_ = states::expect_unquoted_name; + break; + default: + state_ = states::expect_unquoted_name; + break; + } + break; + case states::expect_unquoted_name: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case '.': + err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_name, jsonpath_error_category()), *this); + ++p_; + ++column_; + break; + case '*': + end_all(); + transfer_nodes(); + state_ = states::expect_separator; + ++p_; + ++column_; + break; + default: + state_ = states::unquoted_name; + break; + } + break; + case states::expect_separator: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ' ':case '\t': + ++p_; + ++column_; + break; + case '.': + state_ = states::dot; + break; + case '[': + state_ = states::left_bracket; + break; + default: + err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_separator, jsonpath_error_category()), *this); + break; + }; + ++p_; + ++column_; + break; + case states::expect_right_bracket: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ',': + state_ = states::left_bracket; + break; + case ']': + transfer_nodes(); + state_ = states::expect_separator; + break; + case ' ':case '\t': + break; + default: + err_handler_->fatal_error(std::error_code(jsonpath_parser_errc::expected_right_bracket, jsonpath_error_category()), *this); + break; + } + ++p_; + ++column_; + break; + case states::left_bracket_step: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case '-': + positive_step_ = false; + state_ = states::left_bracket_step2; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + step_ = static_cast<size_t>(*p_-'0'); + state_ = states::left_bracket_step2; + break; + case ']': + end_array_slice(); + transfer_nodes(); + state_ = states::expect_separator; + break; + } + ++p_; + ++column_; + break; + case states::left_bracket_step2: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + step_ = step_*10 + static_cast<size_t>(*p_-'0'); + break; + case ']': + end_array_slice(); + transfer_nodes(); + state_ = states::expect_separator; + break; + } + ++p_; + ++column_; + break; + case states::left_bracket_end: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case '-': + positive_end_ = false; + state_ = states::left_bracket_end2; + break; + case ':': + step_ = 0; + state_ = states::left_bracket_step; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + end_undefined_ = false; + end_ = static_cast<size_t>(*p_-'0'); + state_ = states::left_bracket_end2; + break; + case ']': + end_array_slice(); + transfer_nodes(); + state_ = states::expect_separator; + break; + } + ++p_; + ++column_; + break; + case states::left_bracket_end2: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ':': + step_ = 0; + state_ = states::left_bracket_step; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + end_undefined_ = false; + end_ = end_*10 + static_cast<size_t>(*p_-'0'); + break; + case ']': + end_array_slice(); + transfer_nodes(); + state_ = states::expect_separator; + break; + } + ++p_; + ++column_; + break; + case states::left_bracket_start: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ':': + step_ = 1; + end_undefined_ = true; + state_ = states::left_bracket_end; + break; + case ',': + find_elements(); + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + start_ = start_*10 + static_cast<size_t>(*p_-'0'); + break; + case ']': + find_elements(); + transfer_nodes(); + state_ = states::expect_separator; + break; + } + ++p_; + ++column_; + break; + case states::left_bracket: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case ' ':case '\t': + ++p_; + ++column_; + break; + case '(': + { + if (stack_.back().size() == 1) + { + jsonpath_filter_parser<JsonT> parser(&p_,&line_,&column_); + parser.parse(p_,end_input_); + auto index = parser.eval(*(stack_.back()[0])); + if (index.template is<size_t>()) + { + start_ = index. template as<size_t>(); + find_elements(); + } + else if (index.is_string()) + { + find(index.as_string()); + } + } + else + { + ++p_; + ++column_; + } + } + break; + case '?': + { + jsonpath_filter_parser<JsonT> parser(&p_,&line_,&column_); + parser.parse(p_,end_input_); + nodes_.clear(); + for (size_t j = 0; j < stack_.back().size(); ++j) + { + accept(*(stack_.back()[j]),parser); + } + } + break; + + case ':': + step_ = 1; + end_undefined_ = true; + state_ = states::left_bracket_end; + ++p_; + ++column_; + break; + case ',': + find_elements(); + ++p_; + ++column_; + break; + case '-': + positive_start_ = false; + state_ = states::left_bracket_start; + ++p_; + ++column_; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': + start_ = static_cast<size_t>(*p_-'0'); + state_ = states::left_bracket_start; + ++p_; + ++column_; + break; + case ']': + //find_elements(); + transfer_nodes(); + state_ = states::expect_separator; + ++p_; + ++column_; + break; + case '*': + end_all(); + //transfer_nodes(); + state_ = states::expect_right_bracket; + ++p_; + ++column_; + break; + case '\'': + state_ = states::single_quoted_name; + ++p_; + ++column_; + break; + case '\"': + state_ = states::double_quoted_name; + ++p_; + ++column_; + break; + default: + ++p_; + ++column_; + break; + } + break; + case states::unquoted_name: + switch (*p_) + { + case '\r': + pre_line_break_state_ = state_; + state_ = states::cr; + break; + case '\n': + pre_line_break_state_ = state_; + state_ = states::lf; + break; + case '[': + find(buffer_); + buffer_.clear(); + transfer_nodes(); + start_ = 0; + state_ = states::left_bracket; + break; + case '.': + find(buffer_); + buffer_.clear(); + transfer_nodes(); + state_ = states::dot; + break; + case ' ':case '\t': + break; + default: + buffer_.push_back(*p_); + break; + }; + ++p_; + ++column_; + break; + case states::single_quoted_name: + switch (*p_) + { + case '\'': + find(buffer_); + buffer_.clear(); + state_ = states::expect_right_bracket; + break; + case '\\': + buffer_.push_back(*p_); + if (p_+1 < end_input_) + { + ++p_; + ++column_; + buffer_.push_back(*p_); + } + break; + default: + buffer_.push_back(*p_); + break; + }; + ++p_; + ++column_; + break; + case states::double_quoted_name: + switch (*p_) + { + case '\"': + find(buffer_); + buffer_.clear(); + state_ = states::expect_right_bracket; + break; + case '\\': + buffer_.push_back(*p_); + if (p_+1 < end_input_) + { + ++p_; + ++column_; + buffer_.push_back(*p_); + } + break; + default: + buffer_.push_back(*p_); + break; + }; + ++p_; + ++column_; + break; + default: + ++p_; + ++column_; + break; + } + } + switch (state_) + { + case states::unquoted_name: + { + find(buffer_); + buffer_.clear(); + transfer_nodes(); + } + break; + default: + break; + } + } + + void accept(const JsonT& val, + jsonpath_filter_parser<JsonT>& filter) + { + if (val.is_object()) + { + if (recursive_descent_ && val.is_object()) + { + for (auto it = val.members().begin(); it != val.members().end(); ++it) + { + accept(it->value(),filter); + } + } + if (filter.exists(val)) + { + nodes_.push_back(std::addressof(val)); + } + } + else if (val.is_array()) + { + for (auto it = val.elements().begin(); it != val.elements().end(); ++it) + { + accept(*it,filter); + } + } + } + + + + void end_all() + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + cjson_ptr p = stack_.back()[i]; + if (p->is_array()) + { + for (auto it = p->elements().begin(); it != p->elements().end(); ++it) + { + nodes_.push_back(std::addressof(*it)); + } + } + else if (p->is_object()) + { + for (auto it = p->members().begin(); it != p->members().end(); ++it) + { + nodes_.push_back(std::addressof(it->value())); + } + } + + } + start_ = 0; + } + + void find_elements() + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + cjson_ptr p = stack_.back()[i]; + if (p->is_array() && start_ < p->size()) + { + nodes_.push_back(std::addressof((*p)[start_])); + } + } + start_ = 0; + } + + void end_array_slice() + { + if (positive_step_) + { + end_array_slice1(); + } + else + { + end_array_slice2(); + } + start_ = 0; + end_ = 0; + step_ = 1; + positive_start_ = positive_end_ = positive_step_ = true; + end_undefined_ = true; + } + + void end_array_slice1() + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + cjson_ptr p = stack_.back()[i]; + if (p->is_array()) + { + size_t start = positive_start_ ? start_ : p->size() - start_; + size_t end; + if (!end_undefined_) + { + end = positive_end_ ? end_ : p->size() - end_; + } + else + { + end = p->size(); + } + for (size_t j = start; j < end; j += step_) + { + if (p->is_array() && j < p->size()) + { + nodes_.push_back(std::addressof((*p)[j])); + } + } + } + } + } + + void end_array_slice2() + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + cjson_ptr p = stack_.back()[i]; + size_t start = positive_start_ ? start_ : p->size() - start_; + size_t end; + if (!end_undefined_) + { + end = positive_end_ ? end_ : p->size() - end_; + } + else + { + end = p->size(); + } + + size_t j = end + step_ - 1; + while (j > (start+step_-1)) + { + j -= step_; + if (p->is_array() && j < p->size()) + { + nodes_.push_back(std::addressof((*p)[j])); + } + } + } + } + + void find(const string_type& name) + { + if (name.length() > 0) + { + for (size_t i = 0; i < stack_.back().size(); ++i) + { + find1(*(stack_.back()[i]), name); + } + recursive_descent_ = false; + } + } + + void find1(const JsonT& context_val, const string_type& name) + { + if (context_val.is_object()) + { + if (context_val.count(name) > 0) + { + nodes_.push_back(std::addressof(context_val.at(name))); + } + if (recursive_descent_) + { + for (auto it = context_val.members().begin(); it != context_val.members().end(); ++it) + { + if (it->value().is_object() || it->value().is_array()) + { + find1(it->value(), name); + } + } + } + } + else if (context_val.is_array()) + { + size_t index = 0; + if (try_string_to_index(name.data(),name.size(),&index)) + { + if (index < context_val.size()) + { + nodes_.push_back(std::addressof(context_val[index])); + } + } + else if (name == json_jsonpath_traits<char_type>::length_literal() && context_val.size() > 0) + { + auto q = std::make_shared<JsonT>(context_val.size()); + temp_.push_back(q); + nodes_.push_back(q.get()); + } + if (recursive_descent_) + { + for (auto it = context_val.elements().begin(); it != context_val.elements().end(); ++it) + { + if (it->is_object() || it->is_array()) + { + find1(*it, name); + } + } + } + } + } + + size_t do_line_number() const override + { + return line_; + } + + size_t do_column_number() const override + { + return column_; + } + + char_type do_current_char() const override + { + return 0; //p_ < end_input_? *p_ : 0; + } + +}; + +}} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp new file mode 100644 index 00000000..7f6b6a12 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp @@ -0,0 +1,75 @@ +/// 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_JSONPATH_ERROR_CATEGORY_HPP +#define JSONCONS_JSONPATH_JSONPATH_ERROR_CATEGORY_HPP + +#include "jsoncons/jsoncons.hpp" +#include <system_error> + +namespace jsoncons { namespace jsonpath { + +namespace jsonpath_parser_errc +{ + const int expected_root = 1; + const int expected_right_bracket = 2; + const int expected_name = 3; + const int expected_separator = 4; + const int invalid_filter = 5; + const int invalid_filter_expected_slash = 6; + const int invalid_filter_unbalanced_paren = 7; + const int invalid_filter_unsupported_operator = 8; + const int invalid_filter_expected_right_brace = 9; + const int invalid_filter_expected_primary = 10; +} + +class jsonpath_error_category_impl + : public std::error_category +{ +public: + virtual const char* name() const JSONCONS_NOEXCEPT + { + return "jsonpath"; + } + virtual std::string message(int ev) const + { + switch (ev) + { + case jsonpath_parser_errc::expected_root: + return "Expected $"; + case jsonpath_parser_errc::expected_right_bracket: + return "Expected ]"; + case jsonpath_parser_errc::expected_name: + return "Expected a name following a dot"; + case jsonpath_parser_errc::expected_separator: + return "Expected dot or left bracket separator"; + case jsonpath_parser_errc::invalid_filter: + return "Invalid path filter"; + case jsonpath_parser_errc::invalid_filter_expected_slash: + return "Invalid path filter, expected '/'"; + case jsonpath_parser_errc::invalid_filter_unbalanced_paren: + return "Invalid path filter, unbalanced parenthesis"; + case jsonpath_parser_errc::invalid_filter_unsupported_operator: + return "Unsupported operator"; + case jsonpath_parser_errc::invalid_filter_expected_right_brace: + return "Invalid path filter, expected right brace }"; + case jsonpath_parser_errc::invalid_filter_expected_primary: + return "Invalid path filter, expected primary expression."; + default: + return "Unknown jsonpath parser error"; + } + } +}; + +inline +const std::error_category& jsonpath_error_category() +{ + static jsonpath_error_category_impl instance; + return instance; +} + +}} +#endif 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 |