From 6c910330c4eac6b4461f460bfabc4cbb62be810c Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Thu, 6 Sep 2018 05:00:42 +0000 Subject: [PATCH] Fix json parsing for Struct, ListValue and Value. --- upb/def.c | 15 ++ upb/def.h | 21 ++ upb/json/parser.c | 500 ++++++++++++++++++++++++++++++++++++--------- upb/json/parser.rl | 331 ++++++++++++++++++++++++++++-- 4 files changed, 760 insertions(+), 107 deletions(-) diff --git a/upb/def.c b/upb/def.c index b3114cdeba..0c154e6ccd 100644 --- a/upb/def.c +++ b/upb/def.c @@ -1339,6 +1339,9 @@ bool upb_fielddef_checkdescriptortype(int32_t type) { static const char *kDurationFullMessageName = "google.protobuf.Duration"; static const char *kTimestampFullMessageName = "google.protobuf.Timestamp"; +static const char *kValueFullMessageName = "google.protobuf.Value"; +static const char *kListValueFullMessageName = "google.protobuf.ListValue"; +static const char *kStructFullMessageName = "google.protobuf.Struct"; static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { @@ -1604,6 +1607,18 @@ bool upb_msgdef_timestamp(const upb_msgdef *m) { return strcmp(upb_msgdef_fullname(m), kTimestampFullMessageName) == 0; } +bool upb_msgdef_value(const upb_msgdef *m) { + return strcmp(upb_msgdef_fullname(m), kValueFullMessageName) == 0; +} + +bool upb_msgdef_listvalue(const upb_msgdef *m) { + return strcmp(upb_msgdef_fullname(m), kListValueFullMessageName) == 0; +} + +bool upb_msgdef_structvalue(const upb_msgdef *m) { + return strcmp(upb_msgdef_fullname(m), kStructFullMessageName) == 0; +} + void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { upb_inttable_begin(iter, &m->itof); } diff --git a/upb/def.h b/upb/def.h index 5b9e8e71b6..3886417069 100644 --- a/upb/def.h +++ b/upb/def.h @@ -791,6 +791,15 @@ class upb::MessageDef { /* Is this message a timestamp? */ bool timestamp() const; + /* Is this message a value? */ + bool value() const; + + /* Is this message a list value? */ + bool listvalue() const; + + /* Is this message a struct value? */ + bool structvalue() const; + /* Iteration over fields. The order is undefined. */ class field_iterator : public std::iterator { @@ -934,6 +943,9 @@ void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); bool upb_msgdef_mapentry(const upb_msgdef *m); bool upb_msgdef_duration(const upb_msgdef *m); bool upb_msgdef_timestamp(const upb_msgdef *m); +bool upb_msgdef_value(const upb_msgdef *m); +bool upb_msgdef_listvalue(const upb_msgdef *m); +bool upb_msgdef_structvalue(const upb_msgdef *m); bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); /* Field lookup in a couple of different variations: @@ -1879,6 +1891,15 @@ inline bool MessageDef::duration() const { inline bool MessageDef::timestamp() const { return upb_msgdef_timestamp(this); } +inline bool MessageDef::value() const { + return upb_msgdef_value(this); +} +inline bool MessageDef::listvalue() const { + return upb_msgdef_listvalue(this); +} +inline bool MessageDef::structvalue() const { + return upb_msgdef_structvalue(this); +} inline MessageDef::field_iterator MessageDef::field_begin() { return field_iterator(this); } diff --git a/upb/json/parser.c b/upb/json/parser.c index 81fdba88f5..85c9476737 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -49,6 +49,16 @@ static const char *kBoolValueFullMessageName = "google.protobuf.BoolValue"; static const char *kStringValueFullMessageName = "google.protobuf.StringValue"; static const char *kBytesValueFullMessageName = "google.protobuf.BytesValue"; +/* Type of value message */ +enum { + VALUE_NULLVALUE = 0, + VALUE_NUMBERVALUE = 1, + VALUE_STRINGVALUE = 2, + VALUE_BOOLVALUE = 3, + VALUE_STRUCTVALUE = 4, + VALUE_LISTVALUE = 5 +}; + /* Forward declare */ static bool is_top_level(upb_json_parser *p); @@ -72,9 +82,30 @@ static bool is_timestamp_object(upb_json_parser *p); static bool does_timestamp_start(upb_json_parser *p); static bool does_timestamp_end(upb_json_parser *p); +static bool is_value_object(upb_json_parser *p); +static bool does_value_start(upb_json_parser *p); +static bool does_value_end(upb_json_parser *p); + +static bool is_listvalue_object(upb_json_parser *p); +static bool does_listvalue_start(upb_json_parser *p); +static bool does_listvalue_end(upb_json_parser *p); + +static bool is_structvalue_object(upb_json_parser *p); +static bool does_structvalue_start(upb_json_parser *p); +static bool does_structvalue_end(upb_json_parser *p); + static void start_wrapper_object(upb_json_parser *p); static void end_wrapper_object(upb_json_parser *p); +static void start_value_object(upb_json_parser *p, int value_type); +static void end_value_object(upb_json_parser *p); + +static void start_listvalue_object(upb_json_parser *p); +static void end_listvalue_object(upb_json_parser *p); + +static void start_structvalue_object(upb_json_parser *p); +static void end_structvalue_object(upb_json_parser *p); + static void start_object(upb_json_parser *p); static void end_object(upb_json_parser *p); @@ -668,15 +699,23 @@ static bool end_text(upb_json_parser *p, const char *ptr) { static bool start_number(upb_json_parser *p, const char *ptr) { if (is_top_level(p)) { - if (!is_number_wrapper_object(p)) { + if (is_number_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_NUMBERVALUE); + } else { return false; } - start_wrapper_object(p); } else if (does_number_wrapper_start(p)) { if (!start_subobject(p)) { return false; } start_wrapper_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NUMBERVALUE); } multipart_startaccum(p); @@ -709,6 +748,15 @@ static bool end_number(upb_json_parser *p, const char *ptr) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; } return true; @@ -883,15 +931,23 @@ static bool parser_putbool(upb_json_parser *p, bool val) { static bool end_bool(upb_json_parser *p, bool val) { if (is_top_level(p)) { - if (!is_boolean_wrapper_object(p)) { + if (is_boolean_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_BOOLVALUE); + } else { return false; } - start_wrapper_object(p); } else if (does_boolean_wrapper_start(p)) { if (!start_subobject(p)) { return false; } start_wrapper_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_BOOLVALUE); } if (!parser_putbool(p, val)) { @@ -903,6 +959,47 @@ static bool end_bool(upb_json_parser *p, bool val) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + return true; +} + +static bool end_null(upb_json_parser *p) { + const char *zero_ptr = "0"; + + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + + /* Fill null_value field. */ + multipart_startaccum(p); + capture_begin(p, zero_ptr); + capture_end(p, zero_ptr + 1); + parse_number(p, false); + + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); } return true; @@ -914,6 +1011,8 @@ static bool start_stringval(upb_json_parser *p) { start_wrapper_object(p); } else if (is_timestamp_object(p) || is_duration_object(p)) { start_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_STRINGVALUE); } else { return false; } @@ -927,6 +1026,11 @@ static bool start_stringval(upb_json_parser *p) { return false; } start_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_STRINGVALUE); } if (p->top->f == NULL) { @@ -1062,6 +1166,15 @@ static bool end_stringval(upb_json_parser *p) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; } if (does_timestamp_end(p) || does_duration_end(p)) { @@ -1069,6 +1182,7 @@ static bool end_stringval(upb_json_parser *p) { if (!is_top_level(p)) { end_subobject(p); } + return true; } return true; @@ -1501,10 +1615,6 @@ static void end_member(upb_json_parser *p) { } static bool start_subobject(upb_json_parser *p) { - if (is_top_level(p)) { - return true; - } - if (p->top->f == NULL) { upb_jsonparser_frame *inner; if (!check_stack(p)) return false; @@ -1567,6 +1677,30 @@ static bool start_subobject(upb_json_parser *p) { } } +static bool start_subobject_full(upb_json_parser *p) { + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (is_structvalue_object(p)) { + start_structvalue_object(p); + } else { + return true; + } + } else if (does_structvalue_start(p)) { + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } + + return start_subobject(p); +} + static void end_subobject(upb_json_parser *p) { if (is_top_level(p)) { return; @@ -1588,10 +1722,48 @@ static void end_subobject(upb_json_parser *p) { } } +static void end_subobject_full(upb_json_parser *p) { + end_subobject(p); + + if (does_structvalue_end(p)) { + end_structvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } +} + static bool start_array(upb_json_parser *p) { upb_jsonparser_frame *inner; upb_selector_t sel; + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (is_listvalue_object(p)) { + start_listvalue_object(p); + } else { + return false; + } + } else if (does_listvalue_start(p)) { + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } + UPB_ASSERT(p->top->f); if (!upb_fielddef_isseq(p->top->f)) { @@ -1625,6 +1797,20 @@ static void end_array(upb_json_parser *p) { p->top--; sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); upb_sink_endseq(&p->top->sink, sel); + + if (does_listvalue_end(p)) { + end_listvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } } static void start_object(upb_json_parser *p) { @@ -1711,6 +1897,84 @@ static void end_wrapper_object(upb_json_parser *p) { end_object(p); } +static void start_value_object(upb_json_parser *p, int value_type) { + const char *nullmember = "null_value"; + const char *numbermember = "number_value"; + const char *stringmember = "string_value"; + const char *boolmember = "bool_value"; + const char *structmember = "struct_value"; + const char *listmember = "list_value"; + const char *membername; + + switch (value_type) { + case VALUE_NULLVALUE: + membername = nullmember; + break; + case VALUE_NUMBERVALUE: + membername = numbermember; + break; + case VALUE_STRINGVALUE: + membername = stringmember; + break; + case VALUE_BOOLVALUE: + membername = boolmember; + break; + case VALUE_STRUCTVALUE: + membername = structmember; + break; + case VALUE_LISTVALUE: + membername = listmember; + break; + } + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_value_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_listvalue_object(upb_json_parser *p) { + const char *membername = "values"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_listvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_structvalue_object(upb_json_parser *p) { + const char *membername = "fields"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_structvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + static bool is_top_level(upb_json_parser *p) { return p->top == p->stack && p->top->f == NULL; } @@ -1785,6 +2049,49 @@ static bool is_timestamp_object(upb_json_parser *p) { return p->top->m != NULL && upb_msgdef_timestamp(p->top->m); } +static bool does_value_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_value(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_value_end(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_value(p->top->m); +} + +static bool is_value_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_value(p->top->m); +} + +static bool does_listvalue_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_listvalue(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_listvalue_end(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_listvalue(p->top->m); +} + +static bool is_listvalue_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_listvalue(p->top->m); +} + +static bool does_structvalue_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_structvalue(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_structvalue_end(upb_json_parser *p) { + /* return p->top != p->stack && upb_msgdef_structvalue((p->top - 1)->m); */ + return p->top->m != NULL && upb_msgdef_structvalue(p->top->m); +} + +static bool is_structvalue_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_structvalue(p->top->m); +} + #define CHECK_RETURN_TOP(x) if (!(x)) goto error @@ -1806,27 +2113,26 @@ static bool is_timestamp_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 1945 "upb/json/parser.rl" +#line 2252 "upb/json/parser.rl" -#line 1814 "upb/json/parser.c" +#line 2121 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1, 11, 1, 12, 1, 13, 1, 21, 1, 23, 1, 24, 1, - 25, 1, 26, 1, 27, 1, 28, 1, - 30, 1, 32, 1, 33, 1, 34, 1, - 35, 1, 36, 1, 37, 1, 38, 2, - 4, 9, 2, 5, 6, 2, 7, 3, - 2, 7, 9, 2, 14, 15, 2, 16, - 17, 2, 18, 19, 2, 22, 20, 2, - 24, 26, 2, 25, 26, 2, 29, 2, - 2, 30, 38, 2, 31, 20, 2, 33, - 38, 2, 34, 38, 2, 35, 38, 2, - 37, 38, 3, 25, 22, 20, 4, 14, - 15, 16, 17 + 25, 1, 27, 1, 28, 1, 30, 1, + 32, 1, 33, 1, 34, 1, 35, 1, + 36, 1, 38, 2, 4, 9, 2, 5, + 6, 2, 7, 3, 2, 7, 9, 2, + 14, 15, 2, 16, 17, 2, 18, 19, + 2, 22, 20, 2, 26, 37, 2, 29, + 2, 2, 30, 38, 2, 31, 20, 2, + 33, 38, 2, 34, 38, 2, 35, 38, + 3, 25, 22, 20, 3, 26, 37, 38, + 4, 14, 15, 16, 17 }; static const short _json_key_offsets[] = { @@ -2012,26 +2318,26 @@ static const char _json_trans_targs[] = { }; static const char _json_trans_actions[] = { - 0, 0, 91, 85, 35, 0, 0, 0, - 49, 41, 25, 0, 37, 0, 0, 0, + 0, 0, 84, 78, 33, 0, 0, 0, + 47, 39, 25, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 31, 106, 82, 0, 76, 33, 27, - 0, 0, 25, 29, 29, 79, 0, 0, + 0, 31, 96, 31, 0, 72, 0, 27, + 0, 0, 25, 29, 29, 29, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, - 0, 5, 15, 0, 0, 55, 7, 13, - 0, 58, 9, 9, 9, 61, 64, 11, + 0, 5, 15, 0, 0, 51, 7, 13, + 0, 54, 9, 9, 9, 57, 60, 11, 17, 17, 17, 0, 0, 0, 19, 0, 21, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 110, 67, 110, 0, - 0, 0, 0, 0, 73, 0, 70, 70, - 91, 85, 35, 0, 0, 0, 49, 41, - 53, 88, 25, 0, 37, 0, 0, 0, - 0, 0, 0, 97, 0, 0, 0, 100, - 0, 0, 0, 94, 31, 106, 82, 0, - 76, 33, 27, 0, 0, 25, 29, 29, - 79, 0, 0, 103, 0, 39, 45, 47, - 43, 51 + 0, 0, 0, 0, 104, 63, 104, 0, + 0, 0, 0, 0, 69, 0, 66, 66, + 84, 78, 33, 0, 0, 0, 47, 39, + 49, 81, 25, 0, 35, 0, 0, 0, + 0, 0, 0, 90, 0, 0, 0, 93, + 0, 0, 0, 87, 31, 96, 31, 0, + 72, 0, 27, 0, 0, 25, 29, 29, + 29, 0, 0, 100, 0, 37, 43, 45, + 41, 75 }; static const char _json_eof_actions[] = { @@ -2048,7 +2354,7 @@ static const char _json_eof_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 39, 45, 47, 43, 51, 0, + 0, 0, 37, 43, 45, 41, 75, 0, 0, 0, 0, 0 }; @@ -2062,7 +2368,7 @@ static const int json_en_value_machine = 76; static const int json_en_main = 1; -#line 1948 "upb/json/parser.rl" +#line 2255 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2085,7 +2391,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2089 "upb/json/parser.c" +#line 2395 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2160,83 +2466,83 @@ _match: switch ( *_acts++ ) { case 1: -#line 1819 "upb/json/parser.rl" +#line 2126 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 1821 "upb/json/parser.rl" +#line 2128 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 24; goto _again;} } break; case 3: -#line 1825 "upb/json/parser.rl" +#line 2132 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 1826 "upb/json/parser.rl" +#line 2133 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 1832 "upb/json/parser.rl" +#line 2139 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 1833 "upb/json/parser.rl" +#line 2140 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 1834 "upb/json/parser.rl" +#line 2141 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 1840 "upb/json/parser.rl" +#line 2147 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 1846 "upb/json/parser.rl" +#line 2153 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 1858 "upb/json/parser.rl" +#line 2165 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 1859 "upb/json/parser.rl" +#line 2166 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 1861 "upb/json/parser.rl" +#line 2168 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 1866 "upb/json/parser.rl" +#line 2173 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 1867 "upb/json/parser.rl" +#line 2174 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 1869 "upb/json/parser.rl" +#line 2176 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 1870 "upb/json/parser.rl" +#line 2177 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 1872 "upb/json/parser.rl" +#line 2179 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 1873 "upb/json/parser.rl" +#line 2180 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 1875 "upb/json/parser.rl" +#line 2182 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 1880 "upb/json/parser.rl" +#line 2187 "upb/json/parser.rl" { if (is_timestamp_object(parser)) { {stack[top++] = cs; cs = 48; goto _again;} @@ -2248,78 +2554,78 @@ _match: } break; case 21: -#line 1891 "upb/json/parser.rl" +#line 2198 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 76; goto _again;} } break; case 22: -#line 1896 "upb/json/parser.rl" +#line 2203 "upb/json/parser.rl" { start_member(parser); } break; case 23: -#line 1897 "upb/json/parser.rl" +#line 2204 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 24: -#line 1900 "upb/json/parser.rl" +#line 2207 "upb/json/parser.rl" { end_member(parser); } break; case 25: -#line 1906 "upb/json/parser.rl" +#line 2213 "upb/json/parser.rl" { start_object(parser); } break; case 26: -#line 1909 "upb/json/parser.rl" +#line 2216 "upb/json/parser.rl" { end_object(parser); } break; case 27: -#line 1915 "upb/json/parser.rl" +#line 2222 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 28: -#line 1919 "upb/json/parser.rl" +#line 2226 "upb/json/parser.rl" { end_array(parser); } break; case 29: -#line 1924 "upb/json/parser.rl" +#line 2231 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 30: -#line 1925 "upb/json/parser.rl" +#line 2232 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 31: -#line 1927 "upb/json/parser.rl" +#line 2234 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 32: -#line 1928 "upb/json/parser.rl" +#line 2235 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 33: -#line 1930 "upb/json/parser.rl" +#line 2237 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 1932 "upb/json/parser.rl" +#line 2239 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 1934 "upb/json/parser.rl" - { /* null value */ } +#line 2241 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_null(parser)); } break; case 36: -#line 1936 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_subobject(parser)); } +#line 2243 "upb/json/parser.rl" + { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 37: -#line 1937 "upb/json/parser.rl" - { end_subobject(parser); } +#line 2244 "upb/json/parser.rl" + { end_subobject_full(parser); } break; case 38: -#line 1942 "upb/json/parser.rl" +#line 2249 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 2323 "upb/json/parser.c" +#line 2629 "upb/json/parser.c" } } @@ -2336,30 +2642,34 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 1817 "upb/json/parser.rl" +#line 2124 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; + case 26: +#line 2216 "upb/json/parser.rl" + { end_object(parser); } + break; case 30: -#line 1925 "upb/json/parser.rl" +#line 2232 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 33: -#line 1930 "upb/json/parser.rl" +#line 2237 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 1932 "upb/json/parser.rl" +#line 2239 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 1934 "upb/json/parser.rl" - { /* null value */ } +#line 2241 "upb/json/parser.rl" + { CHECK_RETURN_TOP(end_null(parser)); } break; case 37: -#line 1937 "upb/json/parser.rl" - { end_subobject(parser); } +#line 2244 "upb/json/parser.rl" + { end_subobject_full(parser); } break; -#line 2363 "upb/json/parser.c" +#line 2673 "upb/json/parser.c" } } } @@ -2367,7 +2677,7 @@ _again: _out: {} } -#line 1970 "upb/json/parser.rl" +#line 2277 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -2399,9 +2709,9 @@ bool end(void *closure, const void *hd) { parse(parser, hd, &eof_ch, 0, NULL); return parser->current_state >= -#line 2403 "upb/json/parser.c" +#line 2713 "upb/json/parser.c" 105 -#line 2000 "upb/json/parser.rl" +#line 2307 "upb/json/parser.rl" ; } @@ -2416,13 +2726,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 2420 "upb/json/parser.c" +#line 2730 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2014 "upb/json/parser.rl" +#line 2321 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); diff --git a/upb/json/parser.rl b/upb/json/parser.rl index 2681217094..fc87ddba63 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -47,6 +47,16 @@ static const char *kBoolValueFullMessageName = "google.protobuf.BoolValue"; static const char *kStringValueFullMessageName = "google.protobuf.StringValue"; static const char *kBytesValueFullMessageName = "google.protobuf.BytesValue"; +/* Type of value message */ +enum { + VALUE_NULLVALUE = 0, + VALUE_NUMBERVALUE = 1, + VALUE_STRINGVALUE = 2, + VALUE_BOOLVALUE = 3, + VALUE_STRUCTVALUE = 4, + VALUE_LISTVALUE = 5 +}; + /* Forward declare */ static bool is_top_level(upb_json_parser *p); @@ -70,9 +80,30 @@ static bool is_timestamp_object(upb_json_parser *p); static bool does_timestamp_start(upb_json_parser *p); static bool does_timestamp_end(upb_json_parser *p); +static bool is_value_object(upb_json_parser *p); +static bool does_value_start(upb_json_parser *p); +static bool does_value_end(upb_json_parser *p); + +static bool is_listvalue_object(upb_json_parser *p); +static bool does_listvalue_start(upb_json_parser *p); +static bool does_listvalue_end(upb_json_parser *p); + +static bool is_structvalue_object(upb_json_parser *p); +static bool does_structvalue_start(upb_json_parser *p); +static bool does_structvalue_end(upb_json_parser *p); + static void start_wrapper_object(upb_json_parser *p); static void end_wrapper_object(upb_json_parser *p); +static void start_value_object(upb_json_parser *p, int value_type); +static void end_value_object(upb_json_parser *p); + +static void start_listvalue_object(upb_json_parser *p); +static void end_listvalue_object(upb_json_parser *p); + +static void start_structvalue_object(upb_json_parser *p); +static void end_structvalue_object(upb_json_parser *p); + static void start_object(upb_json_parser *p); static void end_object(upb_json_parser *p); @@ -666,15 +697,23 @@ static bool end_text(upb_json_parser *p, const char *ptr) { static bool start_number(upb_json_parser *p, const char *ptr) { if (is_top_level(p)) { - if (!is_number_wrapper_object(p)) { + if (is_number_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_NUMBERVALUE); + } else { return false; } - start_wrapper_object(p); } else if (does_number_wrapper_start(p)) { if (!start_subobject(p)) { return false; } start_wrapper_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NUMBERVALUE); } multipart_startaccum(p); @@ -707,6 +746,15 @@ static bool end_number(upb_json_parser *p, const char *ptr) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; } return true; @@ -881,15 +929,23 @@ static bool parser_putbool(upb_json_parser *p, bool val) { static bool end_bool(upb_json_parser *p, bool val) { if (is_top_level(p)) { - if (!is_boolean_wrapper_object(p)) { + if (is_boolean_wrapper_object(p)) { + start_wrapper_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_BOOLVALUE); + } else { return false; } - start_wrapper_object(p); } else if (does_boolean_wrapper_start(p)) { if (!start_subobject(p)) { return false; } start_wrapper_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_BOOLVALUE); } if (!parser_putbool(p, val)) { @@ -901,6 +957,47 @@ static bool end_bool(upb_json_parser *p, bool val) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; + } + + return true; +} + +static bool end_null(upb_json_parser *p) { + const char *zero_ptr = "0"; + + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_NULLVALUE); + } else { + return true; + } + + /* Fill null_value field. */ + multipart_startaccum(p); + capture_begin(p, zero_ptr); + capture_end(p, zero_ptr + 1); + parse_number(p, false); + + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); } return true; @@ -912,6 +1009,8 @@ static bool start_stringval(upb_json_parser *p) { start_wrapper_object(p); } else if (is_timestamp_object(p) || is_duration_object(p)) { start_object(p); + } else if (is_value_object(p)) { + start_value_object(p, VALUE_STRINGVALUE); } else { return false; } @@ -925,6 +1024,11 @@ static bool start_stringval(upb_json_parser *p) { return false; } start_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) { + return false; + } + start_value_object(p, VALUE_STRINGVALUE); } if (p->top->f == NULL) { @@ -1060,6 +1164,15 @@ static bool end_stringval(upb_json_parser *p) { if (!is_top_level(p)) { end_subobject(p); } + return true; + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + return true; } if (does_timestamp_end(p) || does_duration_end(p)) { @@ -1067,6 +1180,7 @@ static bool end_stringval(upb_json_parser *p) { if (!is_top_level(p)) { end_subobject(p); } + return true; } return true; @@ -1499,10 +1613,6 @@ static void end_member(upb_json_parser *p) { } static bool start_subobject(upb_json_parser *p) { - if (is_top_level(p)) { - return true; - } - if (p->top->f == NULL) { upb_jsonparser_frame *inner; if (!check_stack(p)) return false; @@ -1565,6 +1675,30 @@ static bool start_subobject(upb_json_parser *p) { } } +static bool start_subobject_full(upb_json_parser *p) { + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (is_structvalue_object(p)) { + start_structvalue_object(p); + } else { + return true; + } + } else if (does_structvalue_start(p)) { + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_STRUCTVALUE); + if (!start_subobject(p)) return false; + start_structvalue_object(p); + } + + return start_subobject(p); +} + static void end_subobject(upb_json_parser *p) { if (is_top_level(p)) { return; @@ -1586,10 +1720,48 @@ static void end_subobject(upb_json_parser *p) { } } +static void end_subobject_full(upb_json_parser *p) { + end_subobject(p); + + if (does_structvalue_end(p)) { + end_structvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } +} + static bool start_array(upb_json_parser *p) { upb_jsonparser_frame *inner; upb_selector_t sel; + if (is_top_level(p)) { + if (is_value_object(p)) { + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (is_listvalue_object(p)) { + start_listvalue_object(p); + } else { + return false; + } + } else if (does_listvalue_start(p)) { + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } else if (does_value_start(p)) { + if (!start_subobject(p)) return false; + start_value_object(p, VALUE_LISTVALUE); + if (!start_subobject(p)) return false; + start_listvalue_object(p); + } + UPB_ASSERT(p->top->f); if (!upb_fielddef_isseq(p->top->f)) { @@ -1623,6 +1795,20 @@ static void end_array(upb_json_parser *p) { p->top--; sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ); upb_sink_endseq(&p->top->sink, sel); + + if (does_listvalue_end(p)) { + end_listvalue_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } + + if (does_value_end(p)) { + end_value_object(p); + if (!is_top_level(p)) { + end_subobject(p); + } + } } static void start_object(upb_json_parser *p) { @@ -1709,6 +1895,84 @@ static void end_wrapper_object(upb_json_parser *p) { end_object(p); } +static void start_value_object(upb_json_parser *p, int value_type) { + const char *nullmember = "null_value"; + const char *numbermember = "number_value"; + const char *stringmember = "string_value"; + const char *boolmember = "bool_value"; + const char *structmember = "struct_value"; + const char *listmember = "list_value"; + const char *membername; + + switch (value_type) { + case VALUE_NULLVALUE: + membername = nullmember; + break; + case VALUE_NUMBERVALUE: + membername = numbermember; + break; + case VALUE_STRINGVALUE: + membername = stringmember; + break; + case VALUE_BOOLVALUE: + membername = boolmember; + break; + case VALUE_STRUCTVALUE: + membername = structmember; + break; + case VALUE_LISTVALUE: + membername = listmember; + break; + } + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_value_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_listvalue_object(upb_json_parser *p) { + const char *membername = "values"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_listvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + +static void start_structvalue_object(upb_json_parser *p) { + const char *membername = "fields"; + + start_object(p); + + /* Set up context for parsing value */ + start_member(p); + capture_begin(p, membername); + capture_end(p, membername + strlen(membername)); + end_membername(p); +} + +static void end_structvalue_object(upb_json_parser *p) { + end_member(p); + end_object(p); +} + static bool is_top_level(upb_json_parser *p) { return p->top == p->stack && p->top->f == NULL; } @@ -1783,6 +2047,49 @@ static bool is_timestamp_object(upb_json_parser *p) { return p->top->m != NULL && upb_msgdef_timestamp(p->top->m); } +static bool does_value_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_value(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_value_end(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_value(p->top->m); +} + +static bool is_value_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_value(p->top->m); +} + +static bool does_listvalue_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_listvalue(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_listvalue_end(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_listvalue(p->top->m); +} + +static bool is_listvalue_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_listvalue(p->top->m); +} + +static bool does_structvalue_start(upb_json_parser *p) { + return p->top->f != NULL && + upb_fielddef_issubmsg(p->top->f) && + upb_msgdef_structvalue(upb_fielddef_msgsubdef(p->top->f)); +} + +static bool does_structvalue_end(upb_json_parser *p) { + /* return p->top != p->stack && upb_msgdef_structvalue((p->top - 1)->m); */ + return p->top->m != NULL && upb_msgdef_structvalue(p->top->m); +} + +static bool is_structvalue_object(upb_json_parser *p) { + return p->top->m != NULL && upb_msgdef_structvalue(p->top->m); +} + #define CHECK_RETURN_TOP(x) if (!(x)) goto error @@ -1906,7 +2213,7 @@ static bool is_timestamp_object(upb_json_parser *p) { >{ start_object(parser); } (member ("," member)*)? "}" - >{ end_object(parser); } + %{ end_object(parser); } ; element = ws value2 ws; @@ -1931,10 +2238,10 @@ static bool is_timestamp_object(upb_json_parser *p) { | "false" %{ CHECK_RETURN_TOP(end_bool(parser, false)); } | "null" - %{ /* null value */ } + %{ CHECK_RETURN_TOP(end_null(parser)); } | object - >{ CHECK_RETURN_TOP(start_subobject(parser)); } - %{ end_subobject(parser); } + >{ CHECK_RETURN_TOP(start_subobject_full(parser)); } + %{ end_subobject_full(parser); } | array; value_machine :=