Skip to content
This repository was archived by the owner on Mar 26, 2020. It is now read-only.

Support event driven parsing. #83

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 53 additions & 6 deletions json11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ struct JsonParser final {
string &err;
bool failed;
const JsonParse strategy;
std::shared_ptr<JsonHandler> handler;

/* fail(msg, err_ret = Json())
*
Expand Down Expand Up @@ -660,10 +661,16 @@ struct JsonParser final {
return parse_string();

if (ch == '{') {
if (handler)
handler->json_object_begin();

map<string, Json> data;
ch = get_next_token();
if (ch == '}')
if (ch == '}') {
if (handler)
handler->json_object_end();
return data;
}

while (1) {
if (ch != '"')
Expand All @@ -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));

Expand All @@ -693,20 +712,31 @@ struct JsonParser final {
}

if (ch == '[') {
if (handler)
handler->json_array_begin();
vector<Json> 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));

Expand Down Expand Up @@ -751,6 +781,23 @@ vector<Json> 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<JsonHandler> 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
*/
Expand Down
35 changes: 35 additions & 0 deletions json11.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ enum JsonParse {
};

class JsonValue;
class JsonHandler;

class Json final {
public:
Expand Down Expand Up @@ -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<JsonHandler> 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<JsonHandler> 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;
Expand Down Expand Up @@ -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