From dae438b4fe6198cbe43fb6e82bd3279545af76da Mon Sep 17 00:00:00 2001 From: Damien Merenne Date: Fri, 2 Dec 2016 13:55:57 +0100 Subject: [PATCH] Support event driven parsing. --- json11.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++------ json11.hpp | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/json11.cpp b/json11.cpp index 0abca07..65fb63c 100644 --- a/json11.cpp +++ b/json11.cpp @@ -340,6 +340,7 @@ struct JsonParser final { string &err; bool failed; const JsonParse strategy; + std::shared_ptr handler; /* fail(msg, err_ret = Json()) * @@ -660,10 +661,16 @@ struct JsonParser final { return parse_string(); if (ch == '{') { + if (handler) + handler->json_object_begin(); + map data; ch = get_next_token(); - if (ch == '}') + if (ch == '}') { + if (handler) + handler->json_object_end(); return data; + } while (1) { if (ch != '"') @@ -677,13 +684,25 @@ struct JsonParser final { if (ch != ':') return fail("expected ':' in object, got " + esc(ch)); - data[std::move(key)] = parse_json(depth + 1); + if (handler) + handler->json_object_key(key); + + Json value = parse_json(depth + 1); + + if (handler) + handler->json_object_value(key, value); + + data[std::move(key)] = value; if (failed) return Json(); ch = get_next_token(); - if (ch == '}') + if (ch == '}') { + if (handler) + handler->json_object_end(); break; + } + if (ch != ',') return fail("expected ',' in object, got " + esc(ch)); @@ -693,20 +712,31 @@ struct JsonParser final { } if (ch == '[') { + if (handler) + handler->json_array_begin(); vector data; ch = get_next_token(); - if (ch == ']') + if (ch == ']') { + if (handler) + handler->json_array_end(); return data; + } while (1) { i--; - data.push_back(parse_json(depth + 1)); + Json value = parse_json(depth + 1); + if (handler) + handler->json_array_value(value); + data.push_back(value); if (failed) return Json(); ch = get_next_token(); - if (ch == ']') + if (ch == ']') { + if (handler) + handler->json_array_end(); break; + } if (ch != ',') return fail("expected ',' in list, got " + esc(ch)); @@ -751,6 +781,23 @@ vector Json::parse_multi(const string &in, return json_vec; } +void Json::parse_event(const string &in, + std::string::size_type &parser_stop_pos, + string &err, + std::shared_ptr handler, + JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + parser.handler = handler; + while (parser.i != in.size() && !parser.failed) { + parser.parse_json(0); + // Check for another object + parser.consume_garbage(); + if (!parser.failed) + parser_stop_pos = parser.i; + } +} + + /* * * * * * * * * * * * * * * * * * * * * Shape-checking */ diff --git a/json11.hpp b/json11.hpp index 5202ef9..f445dc2 100644 --- a/json11.hpp +++ b/json11.hpp @@ -75,6 +75,7 @@ enum JsonParse { }; class JsonValue; +class JsonHandler; class Json final { public: @@ -188,6 +189,24 @@ class Json final { std::string::size_type parser_stop_pos; return parse_multi(in, parser_stop_pos, err, strategy); } + // Parse. If parse fails, return Json() and assign an error message to err. + static void parse_event(const std::string & in, + std::string::size_type & parser_stop_pos, + std::string & err, + std::shared_ptr handler, + JsonParse strategy = JsonParse::STANDARD); + static void parse_event(const char * in, + std::string::size_type & parser_stop_pos, + std::string & err, + std::shared_ptr handler, + JsonParse strategy = JsonParse::STANDARD) { + if (in) { + parse_event(std::string(in), parser_stop_pos, err, handler, strategy); + } else { + err = "null input"; + return; + } + } bool operator== (const Json &rhs) const; bool operator< (const Json &rhs) const; @@ -229,4 +248,20 @@ class JsonValue { virtual ~JsonValue() {} }; +/* event parsing + * + * Callbacks called when parsing the json + */ +class JsonHandler { +public: + virtual ~JsonHandler() {}; + virtual void json_object_begin() = 0; + virtual void json_object_end() = 0; + virtual void json_object_key(const std::string &key) = 0; + virtual void json_object_value(const std::string &key, const Json &value) = 0; + virtual void json_array_begin() = 0; + virtual void json_array_end() = 0; + virtual void json_array_value(const Json &value) = 0; +}; + } // namespace json11