diff --git a/include/jsoncons/json_parser.hpp b/include/jsoncons/json_parser.hpp index cfa2bcce2..26dd5d54e 100644 --- a/include/jsoncons/json_parser.hpp +++ b/include/jsoncons/json_parser.hpp @@ -1451,117 +1451,257 @@ class basic_json_parser : public ser_context void parse_null(basic_json_visitor& visitor, std::error_code& ec) { + static const char_type value[] = {'n','u','l','l'}; + saved_position_ = position_; - if (JSONCONS_LIKELY(input_end_ - input_ptr_ < 4)) + std::ptrdiff_t n = input_end_ - input_ptr_; + std::ptrdiff_t m = 4 - n; + if (JSONCONS_UNLIKELY(n < 4)) { - if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < 4) + bool matches = true; + for (std::ptrdiff_t i = 1; i < n && matches; ++i) { - std::ptrdiff_t diff = input_end_ - input_ptr_; - input_ptr_ += diff; - position_ += diff; - ec = json_errc::invalid_value; - more_ = false; - return; + if (*(input_ptr_+(i)) != value[i]) + { + matches = false; + } } - } - - if (*(input_ptr_+1) == 'u' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 'l') - { - input_ptr_ += 4; - position_ += 4; - more_ = visitor.null_value(semantic_tag::none, *this, ec); - if (parent() == json_parse_state::root) + input_ptr_ += n; + position_ += n; + if (!matches) { - state_ = json_parse_state::accept; + ec = json_errc::invalid_value; + more_ = false; } else { - state_ = json_parse_state::expect_comma_or_end; + if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < m) + { + ec = json_errc::invalid_value; + more_ = false; + } + else + { + matches = true; + for (std::ptrdiff_t i = 0; i < m && matches; ++i) + { + if (*(input_ptr_+(i)) != value[n+i]) + { + matches = false; + } + } + input_ptr_ += m; + position_ += m; + if (!matches) + { + ec = json_errc::invalid_value; + more_ = false; + } + more_ = visitor.null_value(semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } + } } } else { - err_handler_(json_errc::invalid_value, *this); - ec = json_errc::invalid_value; - more_ = false; + if (*(input_ptr_+1) == 'u' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 'l') + { + input_ptr_ += 4; + position_ += 4; + more_ = visitor.null_value(semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } + } + else + { + ec = json_errc::invalid_value; + more_ = false; + } } } void parse_true(basic_json_visitor& visitor, std::error_code& ec) { + static const char_type value[] = {'t','r','u','e'}; + saved_position_ = position_; - if (JSONCONS_LIKELY(input_end_ - input_ptr_ < 4)) + + std::ptrdiff_t n = input_end_ - input_ptr_; + std::ptrdiff_t m = 4 - n; + if (JSONCONS_UNLIKELY(n < 4)) { - if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < 4) + bool matches = true; + for (std::ptrdiff_t i = 1; i < n && matches; ++i) { - std::ptrdiff_t diff = input_end_ - input_ptr_; - input_ptr_ += diff; - position_ += diff; - ec = json_errc::invalid_value; - more_ = false; - return; + if (*(input_ptr_+(i)) != value[i]) + { + matches = false; + } } - } - - if (*(input_ptr_+1) == 'r' && *(input_ptr_+2) == 'u' && *(input_ptr_+3) == 'e') - { - input_ptr_ += 4; - position_ += 4; - more_ = visitor.bool_value(true, semantic_tag::none, *this, ec); - if (parent() == json_parse_state::root) + input_ptr_ += n; + position_ += n; + if (!matches) { - state_ = json_parse_state::accept; + ec = json_errc::invalid_value; + more_ = false; } else { - state_ = json_parse_state::expect_comma_or_end; + if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < m) + { + ec = json_errc::invalid_value; + more_ = false; + } + else + { + matches = true; + for (std::ptrdiff_t i = 0; i < m && matches; ++i) + { + if (*(input_ptr_+(i)) != value[n+i]) + { + matches = false; + } + } + input_ptr_ += m; + position_ += m; + if (!matches) + { + ec = json_errc::invalid_value; + more_ = false; + } + more_ = visitor.bool_value(true, semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } + } } } else { - err_handler_(json_errc::invalid_value, *this); - ec = json_errc::invalid_value; - more_ = false; + if (*(input_ptr_+1) == 'r' && *(input_ptr_+2) == 'u' && *(input_ptr_+3) == 'e') + { + input_ptr_ += 4; + position_ += 4; + more_ = visitor.bool_value(true, semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } + } + else + { + ec = json_errc::invalid_value; + more_ = false; + } } } void parse_false(basic_json_visitor& visitor, std::error_code& ec) { + static const char_type value[] = {'f','a','l','s','e'}; + saved_position_ = position_; - if (JSONCONS_LIKELY(input_end_ - input_ptr_ < 5)) + + std::ptrdiff_t n = input_end_ - input_ptr_; + std::ptrdiff_t m = 5 - n; + if (JSONCONS_UNLIKELY(n < 5)) { - if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < 5) + bool matches = true; + for (std::ptrdiff_t i = 1; i < n && matches; ++i) + { + if (*(input_ptr_+(i)) != value[i]) + { + matches = false; + } + } + input_ptr_ += n; + position_ += n; + if (!matches) { - std::ptrdiff_t diff = input_end_ - input_ptr_; - input_ptr_ += diff; - position_ += diff; ec = json_errc::invalid_value; more_ = false; - return; + } + else + { + if (!chunk_rdr_->read_chunk(ec) || (input_end_ - input_ptr_) < m) + { + ec = json_errc::invalid_value; + more_ = false; + } + else + { + matches = true; + for (std::ptrdiff_t i = 0; i < m && matches; ++i) + { + if (*(input_ptr_+(i)) != value[n+i]) + { + matches = false; + } + } + input_ptr_ += m; + position_ += m; + if (!matches) + { + ec = json_errc::invalid_value; + more_ = false; + } + more_ = visitor.bool_value(false, semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } + } } } - - if (*(input_ptr_+1) == 'a' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 's' && *(input_ptr_+4) == 'e') + else { - input_ptr_ += 5; - position_ += 5; - more_ = visitor.bool_value(false, semantic_tag::none, *this, ec); - if (parent() == json_parse_state::root) + if (*(input_ptr_+1) == 'a' && *(input_ptr_+2) == 'l' && *(input_ptr_+3) == 's' && *(input_ptr_+4) == 'e') { - state_ = json_parse_state::accept; + input_ptr_ += 5; + position_ += 5; + more_ = visitor.bool_value(false, semantic_tag::none, *this, ec); + if (parent() == json_parse_state::root) + { + state_ = json_parse_state::accept; + } + else + { + state_ = json_parse_state::expect_comma_or_end; + } } else { - state_ = json_parse_state::expect_comma_or_end; + ec = json_errc::invalid_value; + more_ = false; } } - else - { - err_handler_(json_errc::invalid_value, *this); - ec = json_errc::invalid_value; - more_ = false; - } } void parse_number(basic_json_visitor& visitor, std::error_code& ec) diff --git a/include/jsoncons/json_reader.hpp b/include/jsoncons/json_reader.hpp index 80bb79ae0..5b2809af3 100644 --- a/include/jsoncons/json_reader.hpp +++ b/include/jsoncons/json_reader.hpp @@ -275,7 +275,7 @@ namespace jsoncons { bool success = false; if (!parser_.stopped()) { - if (parser_.source_exhausted()) + //if (parser_.source_exhausted()) { auto s = source_.read_buffer(ec); if (ec) return false; diff --git a/test/corelib/src/json_reader_tests.cpp b/test/corelib/src/json_reader_tests.cpp index d59b77902..dba042427 100644 --- a/test/corelib/src/json_reader_tests.cpp +++ b/test/corelib/src/json_reader_tests.cpp @@ -23,7 +23,7 @@ TEST_CASE("test json_reader buffered read") std::string int_overflow = std::to_string(m); int_overflow.push_back('0'); - SECTION("test 1") + /*SECTION("test 1") { //input.push_back('['); //input.push_back('"'); @@ -39,10 +39,59 @@ TEST_CASE("test json_reader buffered read") //CHECK(j[1].as() == -123456789.123456789); + }*/ + + SECTION("false with split buffer") + { + std::string str2; + str2.push_back('['); + str2.push_back('"'); + str2.append(stream_source::default_max_buffer_size-8, 'a'); + str2.push_back('"'); + str2.push_back(','); + str2.append("false"); + str2.push_back(']'); + + std::stringstream is(str2); + + auto j = json::parse(is); + + //CHECK(j[1].as() == -123456789.123456789); + } -} -#if 0 + SECTION("true with split buffer") + { + std::string str2; + str2.push_back('['); + str2.push_back('"'); + str2.append(stream_source::default_max_buffer_size - 6, 'a'); + str2.push_back('"'); + str2.push_back(','); + str2.append("true"); + str2.push_back(']'); + + std::stringstream is(str2); + + auto j = json::parse(is); + } + + SECTION("null with split buffer") + { + std::string str2; + str2.push_back('['); + str2.push_back('"'); + str2.append(stream_source::default_max_buffer_size - 5, 'a'); + str2.push_back('"'); + str2.push_back(','); + str2.append("true"); + str2.push_back(']'); + + std::stringstream is(str2); + + auto j = json::parse(is); + } +} void test_json_reader_error(const std::string& text, const std::error_code& ec) { @@ -333,5 +382,3 @@ TEST_CASE("json_reader stateful allocator tests") } } #endif - -#endif