summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.99.2/jsoncons_ext
diff options
context:
space:
mode:
authorManoj Srivastava <srivasta@debian.org>2020-05-22 19:57:41 -0700
committerManoj Srivastava <srivasta@debian.org>2020-05-22 20:02:19 -0700
commitc3d2579ad8d7eb33059aa8fdbaf5b564411a57f2 (patch)
tree1570cda0676fdcf4171a69a7fe313c1b89a52b0c /vendor/jsoncons-0.99.2/jsoncons_ext
parent986b7742bf244b4073ecca0723615f70be8a1ab6 (diff)
parent4e9b9c402ed95bf9a17fd6d795bc49bb4128a6fa (diff)
Merge branch 'upstream' into debian-cmake-fixes
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons_ext')
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/boost/type_extensions.hpp59
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp55
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp341
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp903
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp175
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp445
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/json_query.hpp921
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_error_category.hpp75
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons_ext/jsonpath/jsonpath_filter.hpp1495
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