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

Commit 8711fc1

Browse files
committed
Implement partial parsing support.
This commit implements a consume method that takes a chunk of json, append it to the current data and parses it.
1 parent c77d73f commit 8711fc1

File tree

1 file changed

+158
-113
lines changed

1 file changed

+158
-113
lines changed

json11.cpp

Lines changed: 158 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -815,40 +815,71 @@ struct JsonParserPriv final {
815815
void parse_object() {
816816
assert(states.top() >= VALUE_OBJECT && states.top() <= OBJECT_VALUE);
817817

818-
values.push(map<string, Json>());
818+
switch (states.top()) {
819+
case VALUE_OBJECT:
820+
values.push(map<string, Json>());
821+
set_state(OBJECT_KEY_OR_END);
822+
break;
819823

820-
set_state(OBJECT_KEY_OR_END);
821-
char ch = get_next_token();
822-
if (ch == '}') {
823-
pop_state();
824-
return;
825-
}
824+
case OBJECT_KEY_OR_END: {
825+
char ch = get_next_token();
826826

827-
while (1) {
828827
if (need_data)
829-
return;
828+
break;
829+
830+
if (ch == '}')
831+
return pop_state();
830832

831833
if (ch != '"') {
832834
values.pop();
833-
return fail("expected '\"' in object, got " + esc(ch));
835+
fail("expected '\"' in object, got " + esc(ch));
836+
return;
834837
}
835838

836-
set_state(OBJECT_KEY);
839+
set_state(OBJECT_COLON);
837840
push_state(VALUE_STRING);
838-
parse_string();
841+
842+
break;
843+
}
844+
case OBJECT_COMMA_OR_END: {
845+
char ch = get_next_token();
846+
839847
if (need_data)
848+
break;
849+
850+
if (ch == '}') {
851+
pop_state();
840852
return;
853+
}
841854

842-
string key = values.top().string_value();
843-
values.pop();
855+
if (ch != ',') {
856+
values.pop();
857+
fail("expected ',' or '}' in object, got " + esc(ch));
858+
return;
859+
}
860+
861+
set_state(OBJECT_KEY);
844862

845-
if (failed) {
863+
break;
864+
}
865+
case OBJECT_KEY: {
866+
char ch = get_next_token();
867+
868+
if (need_data)
869+
break;
870+
871+
if (ch != '"') {
846872
values.pop();
847-
return values.push(Json());
873+
return fail("expected '\"' in object, got " + esc(ch));
848874
}
849875

850876
set_state(OBJECT_COLON);
851-
ch = get_next_token();
877+
push_state(VALUE_STRING);
878+
879+
break;
880+
}
881+
case OBJECT_COLON: {
882+
char ch = get_next_token();
852883
if (need_data)
853884
return;
854885

@@ -859,38 +890,23 @@ struct JsonParserPriv final {
859890

860891
set_state(OBJECT_VALUE);
861892
push_state(EXPECT_VALUE);
862-
parse_json();
863-
if (need_data)
864-
return;
865-
893+
break;
894+
}
895+
case OBJECT_VALUE: {
866896
Json value = values.top();
867897
values.pop();
868-
869-
if (failed) {
870-
values.pop();
871-
return values.push(Json());
872-
}
873-
898+
string key = values.top().string_value();
899+
values.pop();
874900
map<string, Json> data = values.top().object_items();
875901
data[std::move(key)] = value;
876902
values.pop();
877903
values.push(data);
878904

879905
set_state(OBJECT_COMMA_OR_END);
880-
ch = get_next_token();
881-
if (need_data)
882-
return;
883-
884-
if (ch == '}') {
885-
pop_state();
886-
break;
887-
}
888-
889-
if (ch != ',') {
890-
values.pop();
891-
return fail("expected ',' in object, got " + esc(ch));
892-
}
893-
ch = get_next_token();
906+
break;
907+
}
908+
default:
909+
assert(false);
894910
}
895911
}
896912

@@ -901,59 +917,62 @@ struct JsonParserPriv final {
901917
void parse_array() {
902918
assert(states.top() >= VALUE_ARRAY && states.top() <= ARRAY_VALUE);
903919

904-
values.push(vector<Json>());
920+
switch (states.top()) {
921+
case VALUE_ARRAY:
922+
values.push(vector<Json>());
923+
set_state(ARRAY_VALUE_OR_END);
924+
break;
905925

906-
set_state(ARRAY_VALUE_OR_END);
907-
char ch = get_next_token();
926+
case ARRAY_VALUE_OR_END: {
927+
char ch = get_next_token();
908928

909-
if (ch == ']') {
910-
pop_state();
911-
return;
912-
}
913-
914-
while (1) {
915929
if (need_data)
916930
return;
917931

932+
if (ch == ']')
933+
return pop_state();
934+
918935
i--;
919936

920937
set_state(ARRAY_VALUE);
921938
push_state(EXPECT_VALUE);
922939

923-
parse_json();
940+
break;
941+
}
942+
case ARRAY_COMMA_OR_END: {
943+
char ch = get_next_token();
924944
if (need_data)
925945
return;
926946

927-
Json value = values.top();
928-
values.pop();
929-
930-
if (failed) {
947+
if (ch == ']') {
948+
pop_state();
949+
return;
950+
}
951+
if (ch != ',') {
931952
values.pop();
932-
return values.push(Json());
953+
fail("expected ',' in list, got " + esc(ch));
954+
return;
933955
}
934956

957+
set_state(ARRAY_VALUE_OR_END);
958+
959+
break;
960+
}
961+
case ARRAY_VALUE: {
962+
Json value = values.top();
963+
values.pop();
964+
935965
vector<Json> data = values.top().array_items();
936966
data.push_back(value);
937967
values.pop();
938968
values.push(data);
939969

940970
set_state(ARRAY_COMMA_OR_END);
941-
ch = get_next_token();
942-
if (need_data)
943-
return;
944-
945-
if (ch == ']') {
946-
pop_state();
947-
break;
948-
}
949-
950-
if (ch != ',') {
951-
values.pop();
952-
return fail("expected ',' in list, got " + esc(ch));
953-
}
954971

955-
ch = get_next_token();
956-
(void)ch;
972+
break;
973+
}
974+
default:
975+
assert(false);
957976
}
958977
}
959978

@@ -974,42 +993,79 @@ struct JsonParserPriv final {
974993

975994
if (ch == '-' || (ch >= '0' && ch <= '9')) {
976995
i--;
977-
set_state(VALUE_NUMBER);
978-
return parse_number();
996+
return set_state(VALUE_NUMBER);
979997
}
980998

981-
if (ch == 't') {
982-
set_state(VALUE_TRUE);
983-
return parse_true();
984-
}
999+
if (ch == 't')
1000+
return set_state(VALUE_TRUE);
9851001

986-
if (ch == 'f') {
987-
set_state(VALUE_FALSE);
988-
return parse_false();
989-
}
1002+
if (ch == 'f')
1003+
return set_state(VALUE_FALSE);
9901004

991-
if (ch == 'n') {
992-
set_state(VALUE_NULL);
993-
return parse_null();
994-
}
1005+
if (ch == 'n')
1006+
return set_state(VALUE_NULL);
9951007

996-
if (ch == '"') {
997-
set_state(VALUE_STRING);
998-
return parse_string();
999-
}
1008+
if (ch == '"')
1009+
return set_state(VALUE_STRING);
10001010

1001-
if (ch == '{') {
1002-
set_state(VALUE_OBJECT);
1003-
return parse_object();
1004-
}
1011+
if (ch == '{')
1012+
return set_state(VALUE_OBJECT);
10051013

1006-
if (ch == '[') {
1007-
set_state(VALUE_ARRAY);
1008-
return parse_array();
1009-
}
1014+
if (ch == '[')
1015+
return set_state(VALUE_ARRAY);
10101016

10111017
return fail("expected value, got " + esc(ch));
10121018
}
1019+
1020+
void consume(const std::string &in = std::string()) {
1021+
need_data = false;
1022+
str += in;
1023+
1024+
/* try to parse as much as possible */
1025+
while (!states.empty()) {
1026+
switch (states.top()) {
1027+
case EXPECT_VALUE:
1028+
parse_json();
1029+
break;
1030+
case VALUE_OBJECT:
1031+
case OBJECT_KEY_OR_END:
1032+
case OBJECT_COMMA_OR_END:
1033+
case OBJECT_KEY:
1034+
case OBJECT_COLON:
1035+
case OBJECT_VALUE:
1036+
parse_object();
1037+
break;
1038+
case VALUE_ARRAY:
1039+
case ARRAY_VALUE_OR_END:
1040+
case ARRAY_COMMA_OR_END:
1041+
case ARRAY_VALUE:
1042+
parse_array();
1043+
break;
1044+
case VALUE_STRING:
1045+
parse_string();
1046+
break;
1047+
case VALUE_NUMBER:
1048+
parse_number();
1049+
break;
1050+
case VALUE_TRUE:
1051+
parse_true();
1052+
break;
1053+
case VALUE_FALSE:
1054+
parse_false();
1055+
break;
1056+
case VALUE_NULL:
1057+
parse_null();
1058+
break;
1059+
case VALUE_COMMENT:
1060+
consume_comment();
1061+
break;
1062+
}
1063+
1064+
if (failed || need_data)
1065+
break;
1066+
}
1067+
}
1068+
10131069
};
10141070

10151071
JsonParser::JsonParser():
@@ -1024,21 +1080,20 @@ JsonParser::~JsonParser() {
10241080
}
10251081

10261082
void JsonParser::consume(const std::string &in) {
1027-
parser->str = in;
1028-
parser->eof = true;
1029-
parser->parse_json();
1083+
parser->consume(in);
10301084
}
10311085

10321086
Json JsonParser::json() const {
1087+
parser->eof = true;
1088+
parser->consume();
10331089
return parser->values.top();
10341090
}
10351091

10361092
Json Json::parse(const string &in, string &err, JsonParse strategy) {
10371093
JsonParserPriv parser { in, err, strategy };
10381094
assert(parser.states.size() == 1);
1039-
10401095
parser.eof = true;
1041-
parser.parse_json();
1096+
parser.consume();
10421097

10431098
// Check for any trailing garbage
10441099
parser.consume_garbage();
@@ -1047,12 +1102,6 @@ Json Json::parse(const string &in, string &err, JsonParse strategy) {
10471102
return Json();
10481103
}
10491104

1050-
if (parser.need_data) {
1051-
/* when doing full parsing, this is an error */
1052-
parser.failed = true;
1053-
parser.values.push(Json());
1054-
}
1055-
10561105
#ifndef NDEBUG
10571106
if (!parser.failed) {
10581107
assert(parser.values.size() == 1);
@@ -1072,11 +1121,7 @@ vector<Json> Json::parse_multi(const string &in,
10721121
parser_stop_pos = 0;
10731122
vector<Json> json_vec;
10741123
while (parser.i != in.size() && !parser.failed && !parser.need_data) {
1075-
parser.parse_json();
1076-
if (parser.need_data) {
1077-
parser.failed = true;
1078-
parser.values.push(Json());
1079-
}
1124+
parser.consume();
10801125
#ifndef NDEBUG
10811126
if (!parser.failed)
10821127
assert(parser.values.size() == 1);

0 commit comments

Comments
 (0)