From 31bfabc4c0868e7d2bf4a97cdafdeb9b966c4fab Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 10 Jan 2018 16:14:43 +0100 Subject: [PATCH] :hammer: optimized input format --- src/json.hpp | 210 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 149 insertions(+), 61 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 9dc0b24aa..9b27d3d9f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5223,59 +5223,7 @@ class binary_reader */ BasicJsonType parse_ubjson_internal(const bool get_char = true) { - switch (get_char ? get() : current) - { - case std::char_traits::eof(): // EOF - JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); - - case 'T': // true - return true; - case 'F': // false - return false; - - case 'Z': // null - return nullptr; - - case 'N': // no-op - return parse_ubjson_internal(); // read next byte - - case 'U': - return get_number(); - case 'i': - return get_number(); - case 'I': - return get_number(); - case 'l': - return get_number(); - case 'L': - return get_number(); - case 'd': - return get_number(); - case 'D': - return get_number(); - - case 'C': // char - { - get(); - check_eof(); - return std::string(1, static_cast(current)); - } - - case 'S': // string - return get_ubjson_string(); - - case '[': // array - return get_ubjson_array(); - - case '{': // object - return get_ubjson_object(); - - default: // anything else - std::stringstream ss; - ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; - JSON_THROW(parse_error::create(112, chars_read, - "error reading UBJSON; last byte: 0x" + ss.str())); - } + return get_ubjson_value(get_char ? get_ignore_noop() : current); } /*! @@ -5293,6 +5241,20 @@ class binary_reader return (current = ia->get_character()); } + /*! + @return character read from the input after ignoring all 'N' entries + */ + int get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + /* @brief read a number from the input @@ -5622,18 +5584,124 @@ class binary_reader } } + std::pair get_ubjson_size_type() + { + std::size_t sz = std::string::npos; + int tc = 0; + + get_ignore_noop(); + + switch (current) + { + case '$': + { + get_ignore_noop(); + check_eof(); + tc = current; + + get_ignore_noop(); + if (current != '#') + { + assert(false); + } + sz = parse_ubjson_internal(); + break; + } + + case '#': + { + sz = parse_ubjson_internal(); + break; + } + + default: + break; + } + + return std::make_pair(sz, tc); + + } + + BasicJsonType get_ubjson_value(const int prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); + + case 'T': // true + return true; + case 'F': // false + return false; + + case 'Z': // null + return nullptr; + + case 'U': + return get_number(); + case 'i': + return get_number(); + case 'I': + return get_number(); + case 'l': + return get_number(); + case 'L': + return get_number(); + case 'd': + return get_number(); + case 'D': + return get_number(); + + case 'C': // char + { + get(); + check_eof(); + return std::string(1, static_cast(current)); + } + + case 'S': // string + return get_ubjson_string(); + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + std::stringstream ss; + ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; + JSON_THROW(parse_error::create(112, chars_read, + "error reading UBJSON; last byte: 0x" + ss.str())); + } + } + BasicJsonType get_ubjson_array() { BasicJsonType result = value_t::array; + const auto size_and_type = get_ubjson_size_type(); - while (get() != ']') + if (size_and_type.first != std::string::npos) { - // skip no-op - if (current == 'N') + for (std::size_t i = 0; i < size_and_type.first; ++i) { - continue; + if (size_and_type.second != 0) + { + result.push_back(get_ubjson_value(size_and_type.second)); + } + else + { + result.push_back(parse_ubjson_internal()); + } + } + } + else + { + while (current != ']') + { + result.push_back(parse_ubjson_internal(false)); + get_ignore_noop(); } - result.push_back(parse_ubjson_internal(false)); } return result; @@ -5642,11 +5710,31 @@ class binary_reader BasicJsonType get_ubjson_object() { BasicJsonType result = value_t::object; + const auto size_and_type = get_ubjson_size_type(); - while (get() != '}') + if (size_and_type.first != std::string::npos) { - auto key = get_ubjson_string(false); - result[std::move(key)] = parse_ubjson_internal(); + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + auto key = get_ubjson_string(); + if (size_and_type.second != 0) + { + result[std::move(key)] = get_ubjson_value(size_and_type.second); + } + else + { + result[std::move(key)] = parse_ubjson_internal(); + } + } + } + else + { + while (current != '}') + { + auto key = get_ubjson_string(false); + result[std::move(key)] = parse_ubjson_internal(); + get_ignore_noop(); + } } return result;