summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp')
-rw-r--r--vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp1587
1 files changed, 1587 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp
new file mode 100644
index 00000000..8a06c2e7
--- /dev/null
+++ b/vendor/jsoncons-0.99.2/jsoncons/json_parser.hpp
@@ -0,0 +1,1587 @@
+// 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_JSON_PARSER_HPP
+#define JSONCONS_JSON_PARSER_HPP
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <stdexcept>
+#include <system_error>
+#include "jsoncons/jsoncons.hpp"
+#include "jsoncons/json_input_handler.hpp"
+#include "jsoncons/parse_error_handler.hpp"
+#include "jsoncons/json_error_category.hpp"
+
+namespace jsoncons {
+
+enum class states
+{
+ root,
+ start,
+ slash,
+ slash_slash,
+ slash_star,
+ slash_star_star,
+ expect_comma_or_end,
+ object,
+ expect_member_name_or_end,
+ expect_member_name,
+ expect_colon,
+ expect_value_or_end,
+ expect_value,
+ array,
+ string,
+ member_name,
+ escape,
+ u1,
+ u2,
+ u3,
+ u4,
+ expect_surrogate_pair1,
+ expect_surrogate_pair2,
+ u6,
+ u7,
+ u8,
+ u9,
+ minus,
+ zero,
+ integer,
+ fraction,
+ exp1,
+ exp2,
+ exp3,
+ n,
+ t,
+ f,
+ cr,
+ lf,
+ done
+};
+
+template<typename CharT>
+class basic_json_parser : private basic_parsing_context<CharT>
+{
+ static const int default_initial_stack_capacity_ = 100;
+
+ std::vector<states> stack_;
+ basic_json_input_handler<CharT> *handler_;
+ basic_parse_error_handler<CharT> *err_handler_;
+ size_t column_;
+ size_t line_;
+ uint32_t cp_;
+ uint32_t cp2_;
+ std::basic_string<CharT> string_buffer_;
+ std::basic_string<char> number_buffer_;
+ bool is_negative_;
+ size_t index_;
+ int initial_stack_capacity_;
+ int nesting_depth_;
+ int max_depth_;
+ float_reader float_reader_;
+ const CharT* begin_input_;
+ const CharT* end_input_;
+ const CharT* p_;
+ uint8_t precision_;
+ std::pair<const CharT*,size_t> literal_;
+ size_t literal_index_;
+
+public:
+ basic_json_parser(basic_json_input_handler<CharT>& handler)
+ : handler_(std::addressof(handler)),
+ err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())),
+ column_(0),
+ line_(0),
+ cp_(0),
+ is_negative_(false),
+ index_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_)
+ {
+ max_depth_ = std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ basic_json_parser(basic_json_input_handler<CharT>& handler,
+ basic_parse_error_handler<CharT>& err_handler)
+ : handler_(std::addressof(handler)),
+ err_handler_(std::addressof(err_handler)),
+ column_(0),
+ line_(0),
+ cp_(0),
+ is_negative_(false),
+ index_(0),
+ initial_stack_capacity_(default_initial_stack_capacity_)
+
+ {
+ max_depth_ = std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP();
+ }
+
+ const basic_parsing_context<CharT>& parsing_context() const
+ {
+ return *this;
+ }
+
+ ~basic_json_parser()
+ {
+ }
+
+ size_t max_nesting_depth() const
+ {
+ return static_cast<size_t>(max_depth_);
+ }
+
+ void max_nesting_depth(size_t max_nesting_depth)
+ {
+ max_depth_ = static_cast<int>(std::min(max_nesting_depth,static_cast<size_t>(std::numeric_limits<int>::max JSONCONS_NO_MACRO_EXP())));
+ }
+
+ states parent() const
+ {
+ return stack_[stack_.size()-2];
+ }
+
+ bool done() const
+ {
+ return stack_.back() == states::done;
+ }
+
+ void do_space()
+ {
+ while ((p_ + 1) < end_input_ && (*(p_ + 1) == ' ' || *(p_ + 1) == '\t'))
+ {
+ ++p_;
+ ++column_;
+ }
+ }
+
+ void do_begin_object()
+ {
+ if (++nesting_depth_ >= max_depth_)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this);
+ }
+ stack_.back() = states::object;
+ stack_.push_back(states::expect_member_name_or_end);
+ handler_->begin_object(*this);
+ }
+
+ void do_end_object()
+ {
+ --nesting_depth_;
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ if (stack_.back() == states::object)
+ {
+ handler_->end_object(*this);
+ }
+ else if (stack_.back() == states::array)
+ {
+ err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this);
+ }
+ else
+ {
+ err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this);
+ }
+
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ stack_.back() = states::done;
+ handler_->end_json();
+ }
+ else
+ {
+ stack_.back() = states::expect_comma_or_end;
+ }
+ }
+
+ void do_begin_array()
+ {
+ if (++nesting_depth_ >= max_depth_)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::max_depth_exceeded, json_error_category()), *this);
+ }
+ stack_.back() = states::array;
+ stack_.push_back(states::expect_value_or_end);
+ handler_->begin_array(*this);
+ }
+
+ void do_end_array()
+ {
+ --nesting_depth_;
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ if (stack_.back() == states::array)
+ {
+ handler_->end_array(*this);
+ }
+ else if (stack_.back() == states::object)
+ {
+ err_handler_->fatal_error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this);
+ }
+ else
+ {
+ err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this);
+ }
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ stack_.back() = states::done;
+ handler_->end_json();
+ }
+ else
+ {
+ stack_.back() = states::expect_comma_or_end;
+ }
+ }
+
+ void begin_parse()
+ {
+ stack_.clear();
+ stack_.reserve(initial_stack_capacity_);
+ stack_.push_back(states::root);
+ stack_.push_back(states::start);
+ line_ = 1;
+ column_ = 1;
+ nesting_depth_ = 0;
+ }
+
+ void check_done(const CharT* input, size_t start, size_t length)
+ {
+ index_ = start;
+ for (; index_ < length; ++index_)
+ {
+ CharT curr_char_ = input[index_];
+ switch (curr_char_)
+ {
+ case '\n':
+ case '\r':
+ case '\t':
+ case ' ':
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::extra_character, json_error_category()), *this);
+ break;
+ }
+ }
+ }
+
+ void parse_string()
+ {
+ const CharT* sb = p_;
+ bool done = false;
+ while (!done && p_ < end_input_)
+ {
+ switch (*p_)
+ {
+ case 0x00:case 0x01:case 0x02:case 0x03:case 0x04:case 0x05:case 0x06:case 0x07:case 0x08:case 0x0b:
+ case 0x0c:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12:case 0x13:case 0x14:case 0x15:case 0x16:
+ case 0x17:case 0x18:case 0x19:case 0x1a:case 0x1b:case 0x1c:case 0x1d:case 0x1e:case 0x1f:
+ string_buffer_.append(sb,p_-sb);
+ column_ += (p_ - sb + 1);
+ err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this);
+ // recovery - skip
+ done = true;
+ ++p_;
+ break;
+ case '\r':
+ {
+ column_ += (p_ - sb + 1);
+ err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this);
+ // recovery - keep
+ string_buffer_.append(sb, p_ - sb + 1);
+ stack_.push_back(states::cr);
+ done = true;
+ ++p_;
+ }
+ break;
+ case '\n':
+ {
+ column_ += (p_ - sb + 1);
+ err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this);
+ // recovery - keep
+ string_buffer_.append(sb, p_ - sb + 1);
+ stack_.push_back(states::lf);
+ done = true;
+ ++p_;
+ }
+ break;
+ case '\t':
+ {
+ column_ += (p_ - sb + 1);
+ err_handler_->error(std::error_code(json_parser_errc::illegal_character_in_string, json_error_category()), *this);
+ // recovery - keep
+ string_buffer_.append(sb, p_ - sb + 1);
+ done = true;
+ ++p_;
+ }
+ break;
+ case '\\':
+ string_buffer_.append(sb,p_-sb);
+ column_ += (p_ - sb + 1);
+ stack_.back() = states::escape;
+ done = true;
+ ++p_;
+ break;
+ case '\"':
+ if (string_buffer_.length() == 0)
+ {
+ end_string_value(sb,p_-sb);
+ }
+ else
+ {
+ string_buffer_.append(sb,p_-sb);
+ end_string_value(string_buffer_.data(),string_buffer_.length());
+ string_buffer_.clear();
+ }
+ column_ += (p_ - sb + 1);
+ done = true;
+ ++p_;
+ break;
+ default:
+ ++p_;
+ break;
+ }
+ }
+ if (!done)
+ {
+ string_buffer_.append(sb,p_-sb);
+ column_ += (p_ - sb + 1);
+ }
+ }
+
+ void parse(const CharT* const input, size_t start, size_t length)
+ {
+ begin_input_ = input + start;
+ end_input_ = input + length;
+ p_ = begin_input_;
+
+ index_ = start;
+ while ((p_ < end_input_) && (stack_.back() != states::done))
+ {
+ switch (*p_)
+ {
+ case 0x00:case 0x01:case 0x02:case 0x03:case 0x04:case 0x05:case 0x06:case 0x07:case 0x08:case 0x0b:
+ case 0x0c:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12:case 0x13:case 0x14:case 0x15:case 0x16:
+ case 0x17:case 0x18:case 0x19:case 0x1a:case 0x1b:case 0x1c:case 0x1d:case 0x1e:case 0x1f:
+ err_handler_->error(std::error_code(json_parser_errc::illegal_control_character, json_error_category()), *this);
+ break;
+ default:
+ break;
+ }
+
+ switch (stack_.back())
+ {
+ case states::cr:
+ ++line_;
+ column_ = 1;
+ switch (*p_)
+ {
+ case '\n':
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ ++p_;
+ break;
+ default:
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ break;
+ }
+ break;
+ case states::lf:
+ ++line_;
+ column_ = 1;
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ break;
+ case states::start:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '{':
+ handler_->begin_json();
+ do_begin_object();
+ break;
+ case '[':
+ handler_->begin_json();
+ do_begin_array();
+ break;
+ case '\"':
+ handler_->begin_json();
+ stack_.back() = states::string;
+ break;
+ case '-':
+ handler_->begin_json();
+ is_negative_ = true;
+ stack_.back() = states::minus;
+ break;
+ case '0':
+ handler_->begin_json();
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::zero;
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ handler_->begin_json();
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ handler_->begin_json();
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ handler_->begin_json();
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ handler_->begin_json();
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::true_literal();
+ literal_index_ = 1;
+ break;
+ case '}':
+ err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_brace, json_error_category()), *this);
+ break;
+ case ']':
+ err_handler_->fatal_error(std::error_code(json_parser_errc::unexpected_right_bracket, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->fatal_error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+
+ case states::expect_comma_or_end:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ do_end_object();
+ break;
+ case ']':
+ do_end_array();
+ break;
+ case ',':
+ begin_member_or_element();
+ break;
+ default:
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::array)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_bracket, json_error_category()), *this);
+ }
+ else if (parent() == states::object)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::expected_comma_or_right_brace, json_error_category()), *this);
+ }
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_member_name_or_end:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ do_end_object();
+ break;
+ case '\"':
+ stack_.back() = states::member_name;
+ stack_.push_back(states::string);
+ break;
+ case '\'':
+ err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_member_name:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '\"':
+ //stack_.back() = states::string;
+ stack_.back() = states::member_name;
+ stack_.push_back(states::string);
+ break;
+ case '}':
+ --nesting_depth_;
+ err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this);
+ break;
+ case '\'':
+ err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_name, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_colon:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case ':':
+ stack_.back() = states::expect_value;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_colon, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_value:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '{':
+ do_begin_object();
+ break;
+ case '[':
+ do_begin_array();
+ break;
+ case '\"':
+ stack_.back() = states::string;
+ break;
+ case '-':
+ is_negative_ = true;
+ stack_.back() = states::minus;
+ break;
+ case '0':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::zero;
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::true_literal();
+ literal_index_ = 1;
+ break;
+ case ']':
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::array)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::extra_comma, json_error_category()), *this);
+ }
+ else
+ {
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ }
+ break;
+ case '\'':
+ err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_value_or_end:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ do_space();
+ break;
+ case '/':
+ stack_.push_back(states::slash);
+ break;
+ case '{':
+ do_begin_object();
+ break;
+ case '[':
+ do_begin_array();
+ break;
+ case ']':
+ do_end_array();
+ break;
+ case '\"':
+ stack_.back() = states::string;
+ break;
+ case '-':
+ is_negative_ = true;
+ stack_.back() = states::minus;
+ break;
+ case '0':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::zero;
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case 'f':
+ stack_.back() = states::f;
+ literal_ = json_literals<CharT>::false_literal();
+ literal_index_ = 1;
+ break;
+ case 'n':
+ stack_.back() = states::n;
+ literal_ = json_literals<CharT>::null_literal();
+ literal_index_ = 1;
+ break;
+ case 't':
+ stack_.back() = states::t;
+ literal_ = json_literals<CharT>::true_literal();
+ literal_index_ = 1;
+ break;
+ case '\'':
+ err_handler_->error(std::error_code(json_parser_errc::single_quote, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::string:
+ parse_string();
+ break;
+ case states::escape:
+ {
+ escape_next_char(*p_);
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u1:
+ {
+ append_codepoint(*p_);
+ stack_.back() = states::u2;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u2:
+ {
+ append_codepoint(*p_);
+ stack_.back() = states::u3;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u3:
+ {
+ append_codepoint(*p_);
+ stack_.back() = states::u4;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u4:
+ {
+ append_codepoint(*p_);
+ if (cp_ >= min_lead_surrogate && cp_ <= max_lead_surrogate)
+ {
+ stack_.back() = states::expect_surrogate_pair1;
+ }
+ else
+ {
+ json_char_traits<CharT, sizeof(CharT)>::append_codepoint_to_string(cp_, string_buffer_);
+ stack_.back() = states::string;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_surrogate_pair1:
+ {
+ switch (*p_)
+ {
+ case '\\':
+ cp2_ = 0;
+ stack_.back() = states::expect_surrogate_pair2;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::expect_surrogate_pair2:
+ {
+ switch (*p_)
+ {
+ case 'u':
+ stack_.back() = states::u6;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_codepoint_surrogate_pair, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u6:
+ {
+ append_second_codepoint(*p_);
+ stack_.back() = states::u7;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u7:
+ {
+ append_second_codepoint(*p_);
+ stack_.back() = states::u8;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u8:
+ {
+ append_second_codepoint(*p_);
+ stack_.back() = states::u9;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::u9:
+ {
+ append_second_codepoint(*p_);
+ uint32_t cp = 0x10000 + ((cp_ & 0x3FF) << 10) + (cp2_ & 0x3FF);
+ json_char_traits<CharT, sizeof(CharT)>::append_codepoint_to_string(cp, string_buffer_);
+ stack_.back() = states::string;
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::minus:
+ {
+ switch (*p_)
+ {
+ case '0':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::zero;
+ break;
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::zero:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ end_integer_value();
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ end_integer_value();
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ end_integer_value();
+ do_space();
+ break;
+ case '/':
+ end_integer_value();
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ end_integer_value();
+ do_end_object();
+ break;
+ case ']':
+ end_integer_value();
+ do_end_array();
+ break;
+ case '.':
+ precision_ = static_cast<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::fraction;
+ break;
+ case ',':
+ end_integer_value();
+ begin_member_or_element();
+ break;
+ case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ err_handler_->error(std::error_code(json_parser_errc::leading_zero, json_error_category()), *this);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::integer:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ end_integer_value();
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ end_integer_value();
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ end_integer_value();
+ do_space();
+ break;
+ case '/':
+ end_integer_value();
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ end_integer_value();
+ do_end_object();
+ break;
+ case ']':
+ end_integer_value();
+ do_end_array();
+ break;
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::integer;
+ break;
+ case '.':
+ precision_ = static_cast<uint8_t>(number_buffer_.length());
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::fraction;
+ break;
+ case ',':
+ end_integer_value();
+ begin_member_or_element();
+ break;
+ case 'e':case 'E':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp1;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::fraction:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ end_fraction_value();
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ end_fraction_value();
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ end_fraction_value();
+ do_space();
+ break;
+ case '/':
+ end_fraction_value();
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ end_fraction_value();
+ do_end_object();
+ break;
+ case ']':
+ end_fraction_value();
+ do_end_array();
+ break;
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ ++precision_;
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::fraction;
+ break;
+ case ',':
+ end_fraction_value();
+ begin_member_or_element();
+ break;
+ case 'e':case 'E':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp1;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::exp1:
+ {
+ switch (*p_)
+ {
+ case '+':
+ stack_.back() = states::exp2;
+ break;
+ case '-':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp2;
+ break;
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp3;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::exp2:
+ {
+ switch (*p_)
+ {
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp3;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::exp3:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ end_fraction_value();
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ end_fraction_value();
+ stack_.push_back(states::lf);
+ break;
+ case ' ':case '\t':
+ end_fraction_value();
+ do_space();
+ break;
+ case '/':
+ end_fraction_value();
+ stack_.push_back(states::slash);
+ break;
+ case '}':
+ end_fraction_value();
+ do_end_object();
+ break;
+ case ']':
+ end_fraction_value();
+ do_end_array();
+ break;
+ case ',':
+ end_fraction_value();
+ begin_member_or_element();
+ break;
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ number_buffer_.push_back(static_cast<char>(*p_));
+ stack_.back() = states::exp3;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::t:
+ while (p_ < end_input_ && literal_index_ < literal_.second)
+ {
+ if (*p_ != literal_.first[literal_index_])
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this);
+ }
+ ++p_;
+ ++literal_index_;
+ ++column_;
+ }
+ if (literal_index_ == literal_.second)
+ {
+ handler_->value(true, *this);
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ stack_.back() = states::done;
+ handler_->end_json();
+ }
+ else
+ {
+ stack_.back() = states::expect_comma_or_end;
+ }
+ }
+ break;
+ case states::f:
+ while (p_ < end_input_ && literal_index_ < literal_.second)
+ {
+ if (*p_ != literal_.first[literal_index_])
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this);
+ }
+ ++p_;
+ ++literal_index_;
+ ++column_;
+ }
+ if (literal_index_ == literal_.second)
+ {
+ handler_->value(false, *this);
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ stack_.back() = states::done;
+ handler_->end_json();
+ }
+ else
+ {
+ stack_.back() = states::expect_comma_or_end;
+ }
+ }
+ break;
+ case states::n:
+ while (p_ < end_input_ && literal_index_ < literal_.second)
+ {
+ if (*p_ != literal_.first[literal_index_])
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_value, json_error_category()), *this);
+ }
+ ++p_;
+ ++literal_index_;
+ ++column_;
+ }
+ if (literal_index_ == literal_.second)
+ {
+ handler_->value(null_type(), *this);
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ stack_.back() = states::done;
+ handler_->end_json();
+ }
+ else
+ {
+ stack_.back() = states::expect_comma_or_end;
+ }
+ }
+ break;
+ case states::slash:
+ {
+ switch (*p_)
+ {
+ case '*':
+ stack_.back() = states::slash_star;
+ break;
+ case '/':
+ stack_.back() = states::slash_slash;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::slash_star:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.push_back(states::cr);
+ break;
+ case '\n':
+ stack_.push_back(states::lf);
+ break;
+ case '*':
+ stack_.back() = states::slash_star_star;
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ case states::slash_slash:
+ {
+ switch (*p_)
+ {
+ case '\r':
+ stack_.pop_back();
+ break;
+ case '\n':
+ stack_.pop_back();
+ break;
+ default:
+ ++p_;
+ ++column_;
+ }
+ }
+ break;
+ case states::slash_star_star:
+ {
+ switch (*p_)
+ {
+ case '/':
+ JSONCONS_ASSERT(!stack_.empty())
+ stack_.pop_back();
+ break;
+ default:
+ stack_.back() = states::slash_star;
+ break;
+ }
+ }
+ ++p_;
+ ++column_;
+ break;
+ default:
+ JSONCONS_THROW_EXCEPTION(std::runtime_error,"Bad parser state");
+ break;
+ }
+ }
+ index_ += (p_-begin_input_);
+ }
+
+ void end_parse()
+ {
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ if (parent() == states::root)
+ {
+ switch (stack_.back())
+ {
+ case states::zero:
+ case states::integer:
+ end_integer_value();
+ break;
+ case states::fraction:
+ case states::exp3:
+ end_fraction_value();
+ break;
+ default:
+ break;
+ }
+ }
+ if (stack_.back() == states::lf || stack_.back() == states::cr)
+ {
+ stack_.pop_back();
+ }
+ if (!(stack_.back() == states::done || stack_.back() == states::start))
+ {
+ err_handler_->error(std::error_code(json_parser_errc::unexpected_eof, json_error_category()), *this);
+ }
+ }
+
+ states state() const
+ {
+ return stack_.back();
+ }
+
+ size_t index() const
+ {
+ return index_;
+ }
+private:
+ void end_fraction_value()
+ {
+ try
+ {
+ double d = float_reader_.read(number_buffer_.data(), precision_);
+ if (is_negative_)
+ d = -d;
+ handler_->value(d, static_cast<uint8_t>(precision_), *this);
+ }
+ catch (...)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ handler_->value(null_type(), *this); // recovery
+ }
+ number_buffer_.clear();
+ is_negative_ = false;
+
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ switch (parent())
+ {
+ case states::array:
+ case states::object:
+ stack_.back() = states::expect_comma_or_end;
+ break;
+ case states::root:
+ stack_.back() = states::done;
+ handler_->end_json();
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ }
+
+ void end_integer_value()
+ {
+ if (is_negative_)
+ {
+ try
+ {
+ int64_t d = string_to_integer(is_negative_, number_buffer_.data(), number_buffer_.length());
+ handler_->value(d, *this);
+ }
+ catch (const std::exception&)
+ {
+ try
+ {
+ double d = float_reader_.read(number_buffer_.data(), number_buffer_.length());
+ handler_->value(-d, static_cast<uint8_t>(number_buffer_.length()), *this);
+ }
+ catch (...)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ handler_->value(null_type(), *this);
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ uint64_t d = string_to_uinteger(number_buffer_.data(), number_buffer_.length());
+ handler_->value(d, *this);
+ }
+ catch (const std::exception&)
+ {
+ try
+ {
+ double d = float_reader_.read(number_buffer_.data(),number_buffer_.length());
+ handler_->value(d, static_cast<uint8_t>(number_buffer_.length()), *this);
+ }
+ catch (...)
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_number, json_error_category()), *this);
+ handler_->value(null_type(), *this);
+ }
+ }
+ }
+
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ switch (parent())
+ {
+ case states::array:
+ case states::object:
+ stack_.back() = states::expect_comma_or_end;
+ break;
+ case states::root:
+ stack_.back() = states::done;
+ handler_->end_json();
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ number_buffer_.clear();
+ is_negative_ = false;
+ }
+
+ void append_codepoint(int c)
+ {
+ switch (c)
+ {
+ case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
+ cp_ = append_to_codepoint(cp_, c);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+
+ void append_second_codepoint(int c)
+ {
+ switch (c)
+ {
+ case '0':
+ case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
+ cp2_ = append_to_codepoint(cp2_, c);
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::expected_value, json_error_category()), *this);
+ break;
+ }
+ }
+
+ void escape_next_char(int next_input)
+ {
+ switch (next_input)
+ {
+ case '\"':
+ string_buffer_.push_back('\"');
+ stack_.back() = states::string;
+ break;
+ case '\\':
+ string_buffer_.push_back('\\');
+ stack_.back() = states::string;
+ break;
+ case '/':
+ string_buffer_.push_back('/');
+ stack_.back() = states::string;
+ break;
+ case 'b':
+ string_buffer_.push_back('\b');
+ stack_.back() = states::string;
+ break;
+ case 'f':
+ string_buffer_.push_back('\f');
+ stack_.back() = states::string;
+ break;
+ case 'n':
+ string_buffer_.push_back('\n');
+ stack_.back() = states::string;
+ break;
+ case 'r':
+ string_buffer_.push_back('\r');
+ stack_.back() = states::string;
+ break;
+ case 't':
+ string_buffer_.push_back('\t');
+ stack_.back() = states::string;
+ break;
+ case 'u':
+ cp_ = 0;
+ stack_.back() = states::u1;
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::illegal_escaped_character, json_error_category()), *this);
+ break;
+ }
+ }
+
+ void end_string_value(const CharT* s, size_t length)
+ {
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ switch (parent())
+ {
+ case states::member_name:
+ handler_->name(s, length, *this);
+ stack_.pop_back();
+ stack_.back() = states::expect_colon;
+ break;
+ case states::object:
+ case states::array:
+ handler_->value(s, length, *this);
+ stack_.back() = states::expect_comma_or_end;
+ break;
+ case states::root:
+ handler_->value(s, length, *this);
+ stack_.back() = states::done;
+ handler_->end_json();
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ }
+
+ void begin_member_or_element()
+ {
+ JSONCONS_ASSERT(stack_.size() >= 2);
+ switch (parent())
+ {
+ case states::object:
+ stack_.back() = states::expect_member_name;
+ break;
+ case states::array:
+ stack_.back() = states::expect_value;
+ break;
+ case states::root:
+ break;
+ default:
+ err_handler_->error(std::error_code(json_parser_errc::invalid_json_text, json_error_category()), *this);
+ break;
+ }
+ }
+
+ uint32_t append_to_codepoint(uint32_t cp, int c)
+ {
+ cp *= 16;
+ if (c >= '0' && c <= '9')
+ {
+ cp += c - '0';
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ cp += c - 'a' + 10;
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ cp += c - 'A' + 10;
+ }
+ else
+ {
+ err_handler_->error(std::error_code(json_parser_errc::invalid_hex_escape_sequence, json_error_category()), *this);
+ }
+ return cp;
+ }
+
+ 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 p_ < end_input_? *p_ : 0;
+ }
+};
+
+typedef basic_json_parser<char> json_parser;
+typedef basic_json_parser<wchar_t> wjson_parser;
+
+}
+
+#endif
+