// Copyright 2018 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_CURSOR_HPP #define JSONCONS_JSON_CURSOR_HPP #include // std::allocator #include #include #include #include #include #include // std::basic_istream #include #include #include #include #include #include #include #include namespace jsoncons { template class basic_staj_event_handler final : public basic_json_content_handler { public: using typename basic_json_content_handler::string_view_type; private: basic_staj_event event_; public: basic_staj_event_handler() : event_(staj_event_type::null_value) { } basic_staj_event_handler(staj_event_type event_type) : event_(event_type) { } const basic_staj_event& event() const { return event_; } private: bool do_begin_object(semantic_tag, const ser_context&) override { event_ = basic_staj_event(staj_event_type::begin_object); return false; } bool do_end_object(const ser_context&) override { event_ = basic_staj_event(staj_event_type::end_object); return false; } bool do_begin_array(semantic_tag, const ser_context&) override { event_ = basic_staj_event(staj_event_type::begin_array); return false; } bool do_end_array(const ser_context&) override { event_ = basic_staj_event(staj_event_type::end_array); return false; } bool do_name(const string_view_type& name, const ser_context&) override { event_ = basic_staj_event(name.data(), name.length(), staj_event_type::name); return false; } bool do_null_value(semantic_tag, const ser_context&) override { event_ = basic_staj_event(staj_event_type::null_value); return false; } bool do_bool_value(bool value, semantic_tag, const ser_context&) override { event_ = basic_staj_event(value); return false; } bool do_string_value(const string_view_type& s, semantic_tag tag, const ser_context&) override { event_ = basic_staj_event(s.data(), s.length(), staj_event_type::string_value, tag); return false; } bool do_byte_string_value(const byte_string_view&, semantic_tag, const ser_context&) override { JSONCONS_UNREACHABLE(); } bool do_int64_value(int64_t value, semantic_tag tag, const ser_context&) override { event_ = basic_staj_event(value, tag); return false; } bool do_uint64_value(uint64_t value, semantic_tag tag, const ser_context&) override { event_ = basic_staj_event(value, tag); return false; } bool do_double_value(double value, semantic_tag tag, const ser_context&) override { event_ = basic_staj_event(value, tag); return false; } void do_flush() override { } }; template,class Allocator=std::allocator> class basic_json_cursor : public basic_staj_reader, private virtual ser_context { public: typedef Src source_type; typedef CharT char_type; typedef Allocator allocator_type; private: static const size_t default_max_buffer_length = 16384; basic_staj_event_handler event_handler_; default_parse_error_handler default_err_handler_; default_basic_staj_filter default_filter_; typedef typename std::allocator_traits:: template rebind_alloc char_allocator_type; basic_json_parser parser_; basic_staj_filter& filter_; source_type source_; std::vector buffer_; size_t buffer_length_; bool eof_; bool begin_; // Noncopyable and nonmoveable basic_json_cursor(const basic_json_cursor&) = delete; basic_json_cursor& operator=(const basic_json_cursor&) = delete; public: typedef basic_string_view string_view_type; // Constructors that throw parse exceptions template basic_json_cursor(Source&& source) : basic_json_cursor(std::forward(source), default_filter_, basic_json_options::default_options(), default_err_handler_) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter) : basic_json_cursor(std::forward(source), filter,basic_json_options::default_options(), default_err_handler_) { } template basic_json_cursor(Source&& source, parse_error_handler& err_handler) : basic_json_cursor(std::forward(source), default_filter_, basic_json_options::default_options(), err_handler) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, parse_error_handler& err_handler) : basic_json_cursor(std::forward(source), filter, basic_json_options::default_options(), err_handler) { } template basic_json_cursor(Source&& source, const basic_json_decode_options& options) : basic_json_cursor(std::forward(source), default_filter_, options, default_err_handler_) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options) : basic_json_cursor(std::forward(source), filter, options, default_err_handler_) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options, parse_error_handler& err_handler, typename std::enable_if,Source>::value>::type* = 0) : parser_(options,err_handler), filter_(filter), source_(source), buffer_length_(default_max_buffer_length), eof_(false), begin_(true) { buffer_.reserve(buffer_length_); if (!done()) { next(); } } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options, parse_error_handler& err_handler, typename std::enable_if,Source>::value>::type* = 0) : parser_(options,err_handler), filter_(filter), buffer_length_(0), eof_(false), begin_(false) { basic_string_view sv(std::forward(source)); auto result = unicons::skip_bom(sv.begin(), sv.end()); if (result.ec != unicons::encoding_errc()) { throw ser_error(result.ec,parser_.line(),parser_.column()); } size_t offset = result.it - sv.begin(); parser_.update(sv.data()+offset,sv.size()-offset); if (!done()) { next(); } } // Constructors that set parse error codes template basic_json_cursor(Source&& source, std::error_code& ec) : basic_json_cursor(std::forward(source),default_filter_,basic_json_options::default_options(),default_err_handler_,ec) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, std::error_code& ec) : basic_json_cursor(std::forward(source), filter, basic_json_options::default_options(), default_err_handler_, ec) { } template basic_json_cursor(Source&& source, parse_error_handler& err_handler, std::error_code& ec) : basic_json_cursor(std::forward(source), default_filter_, basic_json_options::default_options(), err_handler, ec) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, parse_error_handler& err_handler, std::error_code& ec) : basic_json_cursor(std::forward(source), filter, basic_json_options::default_options(), err_handler, ec) { } template basic_json_cursor(Source&& source, const basic_json_decode_options& options, std::error_code& ec) : basic_json_cursor(std::forward(source), default_filter_, options, default_err_handler_, ec) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options, std::error_code& ec) : basic_json_cursor(std::forward(source), filter,options, default_err_handler_, ec) { } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options, parse_error_handler& err_handler, std::error_code& ec, typename std::enable_if,Source>::value>::type* = 0) : parser_(options,err_handler), filter_(filter), source_(source), eof_(false), buffer_length_(default_max_buffer_length), begin_(true) { buffer_.reserve(buffer_length_); if (!done()) { next(ec); } } template basic_json_cursor(Source&& source, basic_staj_filter& filter, const basic_json_decode_options& options, parse_error_handler& err_handler, std::error_code& ec, typename std::enable_if,Source>::value>::type* = 0) : parser_(options,err_handler), filter_(filter), eof_(false), buffer_length_(0), begin_(false) { basic_string_view sv(std::forward(source)); auto result = unicons::skip_bom(sv.begin(), sv.end()); if (result.ec != unicons::encoding_errc()) { ec = result.ec; return; } size_t offset = result.it - sv.begin(); parser_.update(sv.data()+offset,sv.size()-offset); if (!done()) { next(ec); } } size_t buffer_length() const { return buffer_length_; } void buffer_length(size_t length) { buffer_length_ = length; buffer_.reserve(buffer_length_); } bool done() const override { return parser_.done(); } const basic_staj_event& current() const override { return event_handler_.event(); } void accept(basic_json_content_handler& handler) override { std::error_code ec; accept(handler, ec); if (ec) { throw ser_error(ec,parser_.line(),parser_.column()); } } void accept(basic_json_content_handler& handler, std::error_code& ec) override { switch (event_handler_.event().event_type()) { case staj_event_type::begin_array: if (!handler.begin_array(semantic_tag::none, *this)) { return; } break; case staj_event_type::end_array: if (!handler.end_array(*this)) { return; } break; case staj_event_type::begin_object: if (!handler.begin_object(semantic_tag::none, *this)) { return; } break; case staj_event_type::end_object: if (!handler.end_object(*this)) { return; } break; case staj_event_type::name: if (!handler.name(event_handler_.event().template as>(), *this)) { return; } break; case staj_event_type::string_value: if (!handler.string_value(event_handler_.event().template as>(), semantic_tag::none, *this)) { return; } break; case staj_event_type::null_value: if (!handler.null_value(semantic_tag::none, *this)) { return; } break; case staj_event_type::bool_value: if (!handler.bool_value(event_handler_.event().template as(), semantic_tag::none, *this)) { return; } break; case staj_event_type::int64_value: if (!handler.int64_value(event_handler_.event().template as(), semantic_tag::none, *this)) { return; } break; case staj_event_type::uint64_value: if (!handler.uint64_value(event_handler_.event().template as(), semantic_tag::none, *this)) { return; } break; case staj_event_type::double_value: if (!handler.double_value(event_handler_.event().template as(), semantic_tag::none, *this)) { return; } break; default: break; } do { read_next(handler, ec); } while (!ec && !done() && !filter_.accept(event_handler_.event(), *this)); } void next() override { std::error_code ec; next(ec); if (ec) { throw ser_error(ec,parser_.line(),parser_.column()); } } void next(std::error_code& ec) override { do { read_next(ec); } while (!ec && !done() && !filter_.accept(event_handler_.event(), *this)); } void read_buffer(std::error_code& ec) { buffer_.clear(); buffer_.resize(buffer_length_); size_t count = source_.read(buffer_.data(), buffer_length_); buffer_.resize(static_cast(count)); if (buffer_.size() == 0) { eof_ = true; } else if (begin_) { auto result = unicons::skip_bom(buffer_.begin(), buffer_.end()); if (result.ec != unicons::encoding_errc()) { ec = result.ec; return; } size_t offset = result.it - buffer_.begin(); parser_.update(buffer_.data()+offset,buffer_.size()-offset); begin_ = false; } else { parser_.update(buffer_.data(),buffer_.size()); } } void read_next(std::error_code& ec) { read_next(event_handler_, ec); } void read_next(basic_json_content_handler& handler, std::error_code& ec) { parser_.restart(); while (!parser_.stopped()) { if (parser_.source_exhausted()) { if (!source_.eof()) { read_buffer(ec); if (ec) return; } else { eof_ = true; } } parser_.parse_some(handler, ec); if (ec) return; } } void check_done() { std::error_code ec; check_done(ec); if (ec) { throw ser_error(ec,parser_.line(),parser_.column()); } } const ser_context& context() const override { return *this; } void check_done(std::error_code& ec) { try { if (source_.is_error()) { ec = json_errc::source_error; return; } if (eof_) { parser_.check_done(ec); if (ec) return; } else { while (!eof_) { if (parser_.source_exhausted()) { if (!source_.eof()) { read_buffer(ec); if (ec) return; } else { eof_ = true; } } if (!eof_) { parser_.check_done(ec); if (ec) return; } } } } catch (const ser_error& e) { ec = e.code(); } } bool eof() const { return eof_; } size_t line() const override { return parser_.line(); } size_t column() const override { return parser_.column(); } private: }; typedef basic_json_cursor json_cursor; typedef basic_json_cursor wjson_cursor; #if !defined(JSONCONS_NO_DEPRECATED) template> using basic_json_pull_reader = basic_json_cursor; typedef basic_json_cursor json_pull_reader; typedef basic_json_cursor wjson_pull_reader; template> using basic_json_stream_reader = basic_json_cursor; template> using basic_json_staj_reader = basic_json_cursor; typedef basic_json_cursor json_stream_reader; typedef basic_json_cursor wjson_stream_reader; typedef basic_json_cursor json_staj_reader; typedef basic_json_cursor wjson_staj_reader; #endif } #endif