summaryrefslogtreecommitdiff
path: root/upb/json
diff options
context:
space:
mode:
authorBo Yang <teboring@google.com>2018-07-27 05:52:50 +0000
committerBo Yang <teboring@google.com>2018-07-27 05:52:50 +0000
commit20f1b6df41c0a4a2e0516d45fdb81f58fa4814c5 (patch)
treebff27d0cc65c55c10da633b150ef8d1fb395d287 /upb/json
parent1db11440bd57d42bdac674f8df234dc6c51a2cd5 (diff)
Fix json decoding for wrapper messages
Diffstat (limited to 'upb/json')
-rw-r--r--upb/json/parser.rl171
1 files changed, 164 insertions, 7 deletions
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index c731035..9ceb2a5 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -30,6 +30,16 @@
#define UPB_JSON_MAX_DEPTH 64
+static const char *kDoubleValueFullMessageName = "google.protobuf.DoubleValue";
+static const char *kFloatValueFullMessageName = "google.protobuf.FloatValue";
+static const char *kInt64ValueFullMessageName = "google.protobuf.Int64Value";
+static const char *kUInt64ValueFullMessageName = "google.protobuf.UInt64Value";
+static const char *kInt32ValueFullMessageName = "google.protobuf.Int32Value";
+static const char *kUInt32ValueFullMessageName = "google.protobuf.UInt32Value";
+static const char *kBoolValueFullMessageName = "google.protobuf.BoolValue";
+static const char *kStringValueFullMessageName = "google.protobuf.StringValue";
+static const char *kBytesValueFullMessageName = "google.protobuf.BytesValue";
+
typedef struct {
upb_sink sink;
@@ -1229,6 +1239,102 @@ static void end_object(upb_json_parser *p) {
}
}
+static bool is_double_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kDoubleValueFullMessageName) == 0;
+}
+
+static bool is_float_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kFloatValueFullMessageName) == 0;
+}
+
+static bool is_int64_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kInt64ValueFullMessageName) == 0;
+}
+
+static bool is_uint64_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kUInt64ValueFullMessageName) == 0;
+}
+
+static bool is_int32_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kInt32ValueFullMessageName) == 0;
+}
+
+static bool is_uint32_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kUInt32ValueFullMessageName) == 0;
+}
+
+static bool is_bool_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kBoolValueFullMessageName) == 0;
+}
+
+static bool is_string_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kStringValueFullMessageName) == 0;
+}
+
+static bool is_bytes_value(const upb_msgdef *m) {
+ return strcmp(upb_msgdef_fullname(m), kBytesValueFullMessageName) == 0;
+}
+
+static bool is_number_wrapper(const upb_msgdef *m) {
+ return is_double_value(m) ||
+ is_float_value(m) ||
+ is_int64_value(m) ||
+ is_uint64_value(m) ||
+ is_int32_value(m) ||
+ is_uint32_value(m);
+}
+
+static bool is_string_wrapper(const upb_msgdef *m) {
+ return is_string_value(m) ||
+ is_bytes_value(m);
+}
+
+static void start_wrapper_object(upb_json_parser *p) {
+ const char *membername = "value";
+
+ start_object(p);
+
+ /* Set up context for parsing value */
+ start_member(p);
+ capture_begin(p, membername);
+ capture_end(p, membername + 5);
+ end_membername(p);
+}
+
+static void end_wrapper_object(upb_json_parser *p) {
+ end_member(p);
+ end_object(p);
+}
+
+static bool does_number_wrapper_start(upb_json_parser *p) {
+ return p->top->f != NULL &&
+ upb_fielddef_issubmsg(p->top->f) &&
+ is_number_wrapper(upb_fielddef_msgsubdef(p->top->f));
+}
+
+static bool does_number_wrapper_end(upb_json_parser *p) {
+ return p->top->m != NULL && is_number_wrapper(p->top->m);
+}
+
+static bool does_string_wrapper_start(upb_json_parser *p) {
+ return p->top->f != NULL &&
+ upb_fielddef_issubmsg(p->top->f) &&
+ is_string_wrapper(upb_fielddef_msgsubdef(p->top->f));
+}
+
+static bool does_string_wrapper_end(upb_json_parser *p) {
+ return p->top->m != NULL && is_string_wrapper(p->top->m);
+}
+
+static bool does_boolean_wrapper_start(upb_json_parser *p) {
+ return p->top->f != NULL &&
+ upb_fielddef_issubmsg(p->top->f) &&
+ is_bool_value(upb_fielddef_msgsubdef(p->top->f));
+}
+
+static bool does_boolean_wrapper_end(upb_json_parser *p) {
+ return p->top->m != NULL && is_bool_value(p->top->m);
+}
#define CHECK_RETURN_TOP(x) if (!(x)) goto error
@@ -1261,7 +1367,9 @@ static void end_object(upb_json_parser *p) {
number_machine :=
("-"? integer decimal? exponent?)
- <: any >{ fhold; fret; };
+ <: any
+ >{ fhold; fret; }
+ ;
number = /[0-9\-]/ >{ fhold; fcall number_machine; };
text =
@@ -1325,15 +1433,63 @@ static void end_object(upb_json_parser *p) {
value =
number
- >{ start_number(parser, p); }
- %{ CHECK_RETURN_TOP(end_number(parser, p)); }
+ >{
+ if (does_number_wrapper_start(parser)) {
+ CHECK_RETURN_TOP(start_subobject(parser));
+ start_wrapper_object(parser);
+ }
+ start_number(parser, p);
+ }
+ %{
+ CHECK_RETURN_TOP(end_number(parser, p));
+ if (does_number_wrapper_end(parser)) {
+ end_wrapper_object(parser);
+ end_subobject(parser);
+ }
+ }
| string
- >{ CHECK_RETURN_TOP(start_stringval(parser)); }
- @{ CHECK_RETURN_TOP(end_stringval(parser)); }
+ >{
+ if (does_string_wrapper_start(parser)) {
+ CHECK_RETURN_TOP(start_subobject(parser));
+ start_wrapper_object(parser);
+ }
+ CHECK_RETURN_TOP(start_stringval(parser));
+ }
+ @{
+ CHECK_RETURN_TOP(end_stringval(parser));
+ if (does_string_wrapper_end(parser)) {
+ end_wrapper_object(parser);
+ end_subobject(parser);
+ }
+ }
| "true"
- %{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
+ >{
+ if (does_boolean_wrapper_start(parser)) {
+ CHECK_RETURN_TOP(start_subobject(parser));
+ start_wrapper_object(parser);
+ }
+ }
+ %{
+ CHECK_RETURN_TOP(parser_putbool(parser, true));
+ if (does_boolean_wrapper_end(parser)) {
+ end_wrapper_object(parser);
+ end_subobject(parser);
+ }
+ }
| "false"
- %{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
+ >{
+ if (does_boolean_wrapper_start(parser)) {
+ CHECK_RETURN_TOP(start_subobject(parser));
+ start_wrapper_object(parser);
+ }
+ }
+ %{
+ CHECK_RETURN_TOP(parser_putbool(parser, false));
+ if (does_boolean_wrapper_end(parser)) {
+ end_wrapper_object(parser);
+ end_subobject(parser);
+ }
+ }
| "null"
%{ /* null value */ }
| object
@@ -1361,6 +1517,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const char *p = buf;
const char *pe = buf + size;
+ const char *eof = pe;
parser->handle = handle;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback