Fix json encoding/decoding for duration. (#118)

* Fix json encoding/decoding for duration.

* Use lld for int64_t

* Cast int64_t to long
pull/13171/head
Paul Yang 6 years ago committed by GitHub
parent 62318cadce
commit 6c4469e189
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      upb/def.c
  2. 11
      upb/def.h
  3. 559
      upb/json/parser.c
  4. 134
      upb/json/parser.rl
  5. 105
      upb/json/printer.c

@ -1337,6 +1337,7 @@ bool upb_fielddef_checkdescriptortype(int32_t type) {
/* upb_msgdef *****************************************************************/
static const char *kDurationFullMessageName = "google.protobuf.Duration";
static const char *kTimestampFullMessageName = "google.protobuf.Timestamp";
static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
@ -1595,6 +1596,10 @@ bool upb_msgdef_mapentry(const upb_msgdef *m) {
return m->map_entry;
}
bool upb_msgdef_duration(const upb_msgdef *m) {
return strcmp(upb_msgdef_fullname(m), kDurationFullMessageName) == 0;
}
bool upb_msgdef_timestamp(const upb_msgdef *m) {
return strcmp(upb_msgdef_fullname(m), kTimestampFullMessageName) == 0;
}

@ -664,6 +664,10 @@ typedef upb_strtable_iter upb_msg_oneof_iter;
#define UPB_MAPENTRY_VALUE 2
/* Well-known field tag numbers for timestamp messages. */
#define UPB_DURATION_SECONDS 1
#define UPB_DURATION_NANOS 2
/* Well-known field tag numbers for duration messages. */
#define UPB_TIMESTAMP_SECONDS 1
#define UPB_TIMESTAMP_NANOS 2
@ -781,6 +785,9 @@ class upb::MessageDef {
void setmapentry(bool map_entry);
bool mapentry() const;
/* Is this message a duration? */
bool duration() const;
/* Is this message a timestamp? */
bool timestamp() const;
@ -925,6 +932,7 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
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_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
@ -1865,6 +1873,9 @@ inline void MessageDef::setmapentry(bool map_entry) {
inline bool MessageDef::mapentry() const {
return upb_msgdef_mapentry(this);
}
inline bool MessageDef::duration() const {
return upb_msgdef_duration(this);
}
inline bool MessageDef::timestamp() const {
return upb_msgdef_timestamp(this);
}

@ -64,6 +64,10 @@ static bool is_boolean_wrapper_object(upb_json_parser *p);
static bool does_boolean_wrapper_start(upb_json_parser *p);
static bool does_boolean_wrapper_end(upb_json_parser *p);
static bool is_duration_object(upb_json_parser *p);
static bool does_duration_start(upb_json_parser *p);
static bool does_duration_end(upb_json_parser *p);
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);
@ -908,7 +912,7 @@ static bool start_stringval(upb_json_parser *p) {
if (is_top_level(p)) {
if (is_string_wrapper_object(p)) {
start_wrapper_object(p);
} else if (is_timestamp_object(p)) {
} else if (is_timestamp_object(p) || is_duration_object(p)) {
start_object(p);
} else {
return false;
@ -918,7 +922,7 @@ static bool start_stringval(upb_json_parser *p) {
return false;
}
start_wrapper_object(p);
} else if (does_timestamp_start(p)) {
} else if (does_timestamp_start(p) || does_duration_start(p)) {
if (!start_subobject(p)) {
return false;
}
@ -979,7 +983,7 @@ static bool start_stringval(upb_json_parser *p) {
static bool end_stringval_nontop(upb_json_parser *p) {
bool ok = true;
if (is_timestamp_object(p)) {
if (is_timestamp_object(p) || is_duration_object(p)) {
multipart_end(p);
return true;
}
@ -1060,7 +1064,7 @@ static bool end_stringval(upb_json_parser *p) {
}
}
if (does_timestamp_end(p)) {
if (does_timestamp_end(p) || does_duration_end(p)) {
end_object(p);
if (!is_top_level(p)) {
end_subobject(p);
@ -1070,6 +1074,103 @@ static bool end_stringval(upb_json_parser *p) {
return true;
}
static void start_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
static bool end_duration_base(upb_json_parser *p, const char *ptr) {
size_t len;
const char *buf;
char seconds_buf[14];
char nanos_buf[12];
char *end;
int64_t seconds = 0;
int32_t nanos = 0;
double val = 0.0;
const char *seconds_membername = "seconds";
const char *nanos_membername = "nanos";
size_t fraction_start;
if (!capture_end(p, ptr)) {
return false;
}
buf = accumulate_getptr(p, &len);
memset(seconds_buf, 0, 14);
memset(nanos_buf, 0, 12);
/* Find out base end. The maximus duration is 315576000000, which cannot be
* represented by double without losing precision. Thus, we need to handle
* fraction and base separately. */
for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
fraction_start++);
/* Parse base */
memcpy(seconds_buf, buf, fraction_start);
seconds = strtol(seconds_buf, &end, 10);
if (errno == ERANGE || end != seconds_buf + fraction_start) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
seconds_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds > 315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
"maximum acceptable value is "
"315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds < -315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
/* Parse fraction */
nanos_buf[0] = '0';
memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
nanos = val * 1000000000;
if (seconds < 0) nanos = -nanos;
/* Clean up buffer */
multipart_end(p);
/* Set seconds */
start_member(p);
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Set nanos */
start_member(p);
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
multipart_startaccum(p);
return true;
}
static void start_timestamp_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
@ -1656,6 +1757,20 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
return p->top->m != NULL && is_bool_value(p->top->m);
}
static bool does_duration_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
upb_msgdef_duration(upb_fielddef_msgsubdef(p->top->f));
}
static bool does_duration_end(upb_json_parser *p) {
return p->top->m != NULL && upb_msgdef_duration(p->top->m);
}
static bool is_duration_object(upb_json_parser *p) {
return p->top->m != NULL && upb_msgdef_duration(p->top->m);
}
static bool does_timestamp_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
@ -1691,26 +1806,27 @@ static bool is_timestamp_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
#line 1820 "upb/json/parser.rl"
#line 1945 "upb/json/parser.rl"
#line 1699 "upb/json/parser.c"
#line 1814 "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, 18, 1, 20, 1,
21, 1, 22, 1, 23, 1, 24, 1,
25, 1, 27, 1, 29, 1, 30, 1,
31, 1, 32, 1, 33, 1, 34, 1,
35, 2, 4, 9, 2, 5, 6, 2,
7, 3, 2, 7, 9, 2, 11, 12,
2, 13, 14, 2, 15, 16, 2, 19,
17, 2, 21, 23, 2, 22, 23, 2,
26, 2, 2, 27, 35, 2, 28, 17,
2, 30, 35, 2, 31, 35, 2, 32,
35, 2, 34, 35, 3, 22, 19, 17,
4, 11, 12, 13, 14
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
};
static const short _json_key_offsets[] = {
@ -1719,15 +1835,16 @@ static const short _json_key_offsets[] = {
38, 43, 48, 49, 53, 58, 63, 68,
72, 76, 79, 82, 84, 88, 92, 94,
96, 101, 103, 105, 114, 120, 126, 132,
138, 140, 142, 144, 146, 148, 149, 151,
153, 154, 156, 158, 159, 161, 163, 164,
166, 168, 169, 171, 173, 177, 179, 181,
182, 183, 184, 185, 187, 192, 201, 202,
202, 202, 207, 212, 217, 218, 219, 220,
221, 221, 222, 223, 224, 224, 225, 226,
227, 227, 232, 237, 238, 242, 247, 252,
257, 261, 261, 264, 267, 270, 273, 276,
279, 279, 279, 279
138, 140, 144, 147, 149, 151, 154, 155,
159, 161, 163, 165, 167, 168, 170, 172,
173, 175, 177, 178, 180, 182, 183, 185,
187, 188, 190, 192, 196, 198, 200, 201,
202, 203, 204, 206, 211, 220, 221, 221,
221, 226, 231, 236, 237, 238, 239, 240,
240, 241, 242, 243, 243, 244, 245, 246,
246, 251, 256, 257, 261, 266, 271, 276,
280, 280, 283, 286, 289, 292, 295, 298,
298, 298, 298, 298
};
static const char _json_trans_keys[] = {
@ -1748,24 +1865,27 @@ static const char _json_trans_keys[] = {
116, 117, 48, 57, 65, 70, 97, 102,
48, 57, 65, 70, 97, 102, 48, 57,
65, 70, 97, 102, 48, 57, 65, 70,
97, 102, 34, 92, 48, 57, 48, 57,
97, 102, 34, 92, 45, 48, 49, 57,
48, 49, 57, 46, 115, 48, 57, 115,
48, 57, 34, 46, 115, 48, 57, 48,
57, 48, 57, 48, 57, 48, 57, 45,
48, 57, 48, 57, 45, 48, 57, 48,
57, 45, 48, 57, 48, 57, 84, 48,
57, 84, 48, 57, 48, 57, 58, 48,
57, 48, 57, 58, 48, 57, 48, 57,
58, 48, 57, 48, 57, 43, 45, 46,
90, 48, 57, 48, 57, 58, 48, 48,
34, 48, 57, 43, 45, 90, 48, 57,
34, 45, 91, 102, 110, 116, 123, 48,
57, 34, 32, 93, 125, 9, 13, 32,
44, 93, 9, 13, 32, 93, 125, 9,
13, 97, 108, 115, 101, 117, 108, 108,
114, 117, 101, 32, 34, 125, 9, 13,
32, 34, 125, 9, 13, 34, 32, 58,
9, 13, 32, 93, 125, 9, 13, 32,
44, 125, 9, 13, 32, 44, 125, 9,
13, 32, 34, 9, 13, 32, 9, 13,
43, 45, 46, 90, 48, 57, 48, 57,
58, 48, 48, 34, 48, 57, 43, 45,
90, 48, 57, 34, 45, 91, 102, 110,
116, 123, 48, 57, 34, 32, 93, 125,
9, 13, 32, 44, 93, 9, 13, 32,
93, 125, 9, 13, 97, 108, 115, 101,
117, 108, 108, 114, 117, 101, 32, 34,
125, 9, 13, 32, 34, 125, 9, 13,
34, 32, 58, 9, 13, 32, 93, 125,
9, 13, 32, 44, 125, 9, 13, 32,
44, 125, 9, 13, 32, 34, 9, 13,
32, 9, 13, 32, 9, 13, 32, 9,
13, 32, 9, 13, 32, 9, 13, 0
13, 32, 9, 13, 32, 9, 13, 32,
9, 13, 0
};
static const char _json_single_lengths[] = {
@ -1774,14 +1894,15 @@ static const char _json_single_lengths[] = {
3, 3, 1, 2, 3, 3, 3, 2,
2, 1, 3, 0, 2, 2, 0, 0,
3, 2, 2, 9, 0, 0, 0, 0,
2, 0, 0, 0, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0, 1, 0,
0, 1, 0, 0, 4, 0, 0, 1,
1, 1, 1, 0, 3, 7, 1, 0,
0, 3, 3, 3, 1, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 3, 3, 1, 2, 3, 3, 3,
2, 0, 1, 1, 1, 1, 1, 1,
2, 2, 1, 2, 0, 1, 1, 2,
0, 0, 0, 0, 1, 0, 0, 1,
0, 0, 1, 0, 0, 1, 0, 0,
1, 0, 0, 4, 0, 0, 1, 1,
1, 1, 0, 3, 7, 1, 0, 0,
3, 3, 3, 1, 1, 1, 1, 0,
1, 1, 1, 0, 1, 1, 1, 0,
3, 3, 1, 2, 3, 3, 3, 2,
0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0
};
@ -1791,14 +1912,15 @@ static const char _json_range_lengths[] = {
1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
1, 0, 0, 0, 3, 3, 3, 3,
0, 1, 1, 1, 1, 0, 1, 1,
0, 1, 1, 0, 1, 1, 0, 1,
1, 0, 1, 1, 0, 1, 1, 0,
0, 0, 0, 1, 1, 1, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 0, 1, 1, 0,
1, 1, 0, 1, 1, 0, 1, 1,
0, 1, 1, 0, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0,
1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1,
1, 1, 0, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0
};
@ -1808,15 +1930,16 @@ static const short _json_index_offsets[] = {
48, 53, 58, 60, 64, 69, 74, 79,
83, 87, 90, 94, 96, 100, 104, 106,
108, 113, 116, 119, 129, 133, 137, 141,
145, 148, 150, 152, 154, 156, 158, 160,
162, 164, 166, 168, 170, 172, 174, 176,
178, 180, 182, 184, 186, 191, 193, 195,
197, 199, 201, 203, 205, 210, 219, 221,
222, 223, 228, 233, 238, 240, 242, 244,
246, 247, 249, 251, 253, 254, 256, 258,
260, 261, 266, 271, 273, 277, 282, 287,
292, 296, 297, 300, 303, 306, 309, 312,
315, 316, 317, 318
145, 148, 152, 155, 158, 160, 163, 165,
169, 171, 173, 175, 177, 179, 181, 183,
185, 187, 189, 191, 193, 195, 197, 199,
201, 203, 205, 207, 212, 214, 216, 218,
220, 222, 224, 226, 231, 240, 242, 243,
244, 249, 254, 259, 261, 263, 265, 267,
268, 270, 272, 274, 275, 277, 279, 281,
282, 287, 292, 294, 298, 303, 308, 313,
317, 318, 321, 324, 327, 330, 333, 336,
337, 338, 339, 340
};
static const unsigned char _json_indicies[] = {
@ -1838,72 +1961,77 @@ static const unsigned char _json_indicies[] = {
55, 55, 55, 55, 55, 55, 55, 56,
1, 57, 57, 57, 1, 58, 58, 58,
1, 59, 59, 59, 1, 60, 60, 60,
1, 62, 63, 61, 64, 1, 65, 1,
66, 1, 67, 1, 68, 1, 69, 1,
70, 1, 71, 1, 72, 1, 73, 1,
74, 1, 75, 1, 76, 1, 77, 1,
78, 1, 79, 1, 80, 1, 81, 1,
82, 1, 83, 83, 84, 85, 1, 86,
1, 87, 1, 88, 1, 89, 1, 90,
1, 91, 1, 92, 1, 93, 93, 94,
92, 1, 95, 96, 97, 98, 99, 100,
101, 96, 1, 102, 1, 103, 104, 106,
107, 1, 106, 105, 108, 109, 107, 108,
1, 109, 1, 1, 109, 105, 110, 1,
111, 1, 112, 1, 113, 1, 114, 115,
1, 116, 1, 117, 1, 118, 119, 1,
120, 1, 121, 1, 122, 123, 124, 125,
123, 1, 126, 127, 128, 126, 1, 129,
1, 130, 131, 130, 1, 131, 1, 1,
131, 132, 133, 134, 135, 133, 1, 136,
137, 128, 136, 1, 137, 127, 137, 1,
138, 139, 139, 1, 140, 140, 1, 141,
141, 1, 142, 142, 1, 143, 143, 1,
144, 144, 1, 1, 1, 1, 1, 0
1, 62, 63, 61, 64, 65, 66, 1,
67, 68, 1, 69, 70, 1, 71, 1,
70, 71, 1, 72, 1, 69, 70, 68,
1, 73, 1, 74, 1, 75, 1, 76,
1, 77, 1, 78, 1, 79, 1, 80,
1, 81, 1, 82, 1, 83, 1, 84,
1, 85, 1, 86, 1, 87, 1, 88,
1, 89, 1, 90, 1, 91, 1, 92,
92, 93, 94, 1, 95, 1, 96, 1,
97, 1, 98, 1, 99, 1, 100, 1,
101, 1, 102, 102, 103, 101, 1, 104,
105, 106, 107, 108, 109, 110, 105, 1,
111, 1, 112, 113, 115, 116, 1, 115,
114, 117, 118, 116, 117, 1, 118, 1,
1, 118, 114, 119, 1, 120, 1, 121,
1, 122, 1, 123, 124, 1, 125, 1,
126, 1, 127, 128, 1, 129, 1, 130,
1, 131, 132, 133, 134, 132, 1, 135,
136, 137, 135, 1, 138, 1, 139, 140,
139, 1, 140, 1, 1, 140, 141, 142,
143, 144, 142, 1, 145, 146, 137, 145,
1, 146, 136, 146, 1, 147, 148, 148,
1, 149, 149, 1, 150, 150, 1, 151,
151, 1, 152, 152, 1, 153, 153, 1,
1, 1, 1, 1, 1, 0
};
static const char _json_trans_targs[] = {
1, 0, 2, 99, 3, 6, 10, 13,
16, 98, 4, 3, 98, 4, 5, 7,
8, 9, 100, 11, 12, 101, 14, 15,
102, 17, 18, 103, 17, 18, 103, 19,
19, 20, 21, 22, 23, 103, 22, 23,
25, 26, 32, 104, 27, 29, 28, 30,
31, 34, 105, 35, 34, 105, 35, 33,
36, 37, 38, 39, 40, 34, 105, 35,
42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 67, 66, 62, 63,
64, 65, 66, 106, 68, 61, 66, 70,
72, 73, 76, 81, 85, 89, 71, 107,
107, 74, 73, 71, 74, 75, 77, 78,
79, 80, 107, 82, 83, 84, 107, 86,
87, 88, 107, 90, 91, 97, 90, 91,
97, 92, 92, 93, 94, 95, 96, 97,
95, 96, 107, 98, 98, 98, 98, 98,
98
1, 0, 2, 106, 3, 6, 10, 13,
16, 105, 4, 3, 105, 4, 5, 7,
8, 9, 107, 11, 12, 108, 14, 15,
109, 17, 18, 110, 17, 18, 110, 19,
19, 20, 21, 22, 23, 110, 22, 23,
25, 26, 32, 111, 27, 29, 28, 30,
31, 34, 112, 35, 34, 112, 35, 33,
36, 37, 38, 39, 40, 34, 112, 35,
42, 43, 47, 43, 47, 44, 46, 45,
113, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 74, 73, 69,
70, 71, 72, 73, 114, 75, 68, 73,
77, 79, 80, 83, 88, 92, 96, 78,
115, 115, 81, 80, 78, 81, 82, 84,
85, 86, 87, 115, 89, 90, 91, 115,
93, 94, 95, 115, 97, 98, 104, 97,
98, 104, 99, 99, 100, 101, 102, 103,
104, 102, 103, 115, 105, 105, 105, 105,
105, 105
};
static const char _json_trans_actions[] = {
0, 0, 85, 79, 29, 0, 0, 0,
43, 35, 19, 0, 31, 0, 0, 0,
0, 0, 91, 85, 35, 0, 0, 0,
49, 41, 25, 0, 37, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 25, 100, 76, 0, 70, 27, 21,
0, 0, 19, 23, 23, 73, 0, 0,
0, 31, 106, 82, 0, 76, 33, 27,
0, 0, 25, 29, 29, 79, 0, 0,
0, 0, 0, 3, 0, 0, 0, 0,
0, 5, 15, 0, 0, 49, 7, 13,
0, 52, 9, 9, 9, 55, 58, 11,
17, 0, 0, 0, 0, 0, 0, 0,
0, 5, 15, 0, 0, 55, 7, 13,
0, 58, 9, 9, 9, 61, 64, 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, 104, 61, 104, 0, 0,
0, 0, 0, 67, 0, 64, 64, 85,
79, 29, 0, 0, 0, 43, 35, 47,
82, 19, 0, 31, 0, 0, 0, 0,
0, 0, 91, 0, 0, 0, 94, 0,
0, 0, 88, 25, 100, 76, 0, 70,
27, 21, 0, 0, 19, 23, 23, 73,
0, 0, 97, 0, 33, 39, 41, 37,
45
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
};
static const char _json_eof_actions[] = {
@ -1919,7 +2047,8 @@ 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, 0, 33, 39, 41, 37, 45,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 39, 45, 47, 43, 51, 0,
0, 0, 0, 0
};
@ -1927,12 +2056,13 @@ static const int json_start = 1;
static const int json_en_number_machine = 24;
static const int json_en_string_machine = 33;
static const int json_en_timestamp_machine = 41;
static const int json_en_value_machine = 69;
static const int json_en_duration_machine = 41;
static const int json_en_timestamp_machine = 48;
static const int json_en_value_machine = 76;
static const int json_en_main = 1;
#line 1823 "upb/json/parser.rl"
#line 1948 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@ -1955,7 +2085,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
#line 1959 "upb/json/parser.c"
#line 2089 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@ -2030,152 +2160,166 @@ _match:
switch ( *_acts++ )
{
case 1:
#line 1704 "upb/json/parser.rl"
#line 1819 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 2:
#line 1706 "upb/json/parser.rl"
#line 1821 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 24; goto _again;} }
break;
case 3:
#line 1710 "upb/json/parser.rl"
#line 1825 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 4:
#line 1711 "upb/json/parser.rl"
#line 1826 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 5:
#line 1717 "upb/json/parser.rl"
#line 1832 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 6:
#line 1718 "upb/json/parser.rl"
#line 1833 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 7:
#line 1719 "upb/json/parser.rl"
#line 1834 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 8:
#line 1725 "upb/json/parser.rl"
#line 1840 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 9:
#line 1731 "upb/json/parser.rl"
#line 1846 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 10:
#line 1743 "upb/json/parser.rl"
{ start_timestamp_base(parser, p); }
#line 1858 "upb/json/parser.rl"
{ start_duration_base(parser, p); }
break;
case 11:
#line 1744 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_base(parser, p)); }
#line 1859 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break;
case 12:
#line 1746 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
#line 1861 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 13:
#line 1747 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
#line 1866 "upb/json/parser.rl"
{ start_timestamp_base(parser, p); }
break;
case 14:
#line 1749 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
#line 1867 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_base(parser, p)); }
break;
case 15:
#line 1750 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
#line 1869 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
break;
case 16:
#line 1752 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
#line 1870 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break;
case 17:
#line 1757 "upb/json/parser.rl"
#line 1872 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
break;
case 18:
#line 1873 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break;
case 19:
#line 1875 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 20:
#line 1880 "upb/json/parser.rl"
{
if (is_timestamp_object(parser)) {
{stack[top++] = cs; cs = 48; goto _again;}
} else if (is_duration_object(parser)) {
{stack[top++] = cs; cs = 41; goto _again;}
} else {
{stack[top++] = cs; cs = 33; goto _again;}
}
}
break;
case 18:
#line 1766 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 69; goto _again;} }
case 21:
#line 1891 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 76; goto _again;} }
break;
case 19:
#line 1771 "upb/json/parser.rl"
case 22:
#line 1896 "upb/json/parser.rl"
{ start_member(parser); }
break;
case 20:
#line 1772 "upb/json/parser.rl"
case 23:
#line 1897 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 21:
#line 1775 "upb/json/parser.rl"
case 24:
#line 1900 "upb/json/parser.rl"
{ end_member(parser); }
break;
case 22:
#line 1781 "upb/json/parser.rl"
case 25:
#line 1906 "upb/json/parser.rl"
{ start_object(parser); }
break;
case 23:
#line 1784 "upb/json/parser.rl"
case 26:
#line 1909 "upb/json/parser.rl"
{ end_object(parser); }
break;
case 24:
#line 1790 "upb/json/parser.rl"
case 27:
#line 1915 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 25:
#line 1794 "upb/json/parser.rl"
case 28:
#line 1919 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 26:
#line 1799 "upb/json/parser.rl"
case 29:
#line 1924 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); }
break;
case 27:
#line 1800 "upb/json/parser.rl"
case 30:
#line 1925 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 28:
#line 1802 "upb/json/parser.rl"
case 31:
#line 1927 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 29:
#line 1803 "upb/json/parser.rl"
case 32:
#line 1928 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 30:
#line 1805 "upb/json/parser.rl"
case 33:
#line 1930 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 31:
#line 1807 "upb/json/parser.rl"
case 34:
#line 1932 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 32:
#line 1809 "upb/json/parser.rl"
case 35:
#line 1934 "upb/json/parser.rl"
{ /* null value */ }
break;
case 33:
#line 1811 "upb/json/parser.rl"
case 36:
#line 1936 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject(parser)); }
break;
case 34:
#line 1812 "upb/json/parser.rl"
case 37:
#line 1937 "upb/json/parser.rl"
{ end_subobject(parser); }
break;
case 35:
#line 1817 "upb/json/parser.rl"
case 38:
#line 1942 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
#line 2179 "upb/json/parser.c"
#line 2323 "upb/json/parser.c"
}
}
@ -2192,30 +2336,30 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 0:
#line 1702 "upb/json/parser.rl"
#line 1817 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 27:
#line 1800 "upb/json/parser.rl"
case 30:
#line 1925 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 30:
#line 1805 "upb/json/parser.rl"
case 33:
#line 1930 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 31:
#line 1807 "upb/json/parser.rl"
case 34:
#line 1932 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 32:
#line 1809 "upb/json/parser.rl"
case 35:
#line 1934 "upb/json/parser.rl"
{ /* null value */ }
break;
case 34:
#line 1812 "upb/json/parser.rl"
case 37:
#line 1937 "upb/json/parser.rl"
{ end_subobject(parser); }
break;
#line 2219 "upb/json/parser.c"
#line 2363 "upb/json/parser.c"
}
}
}
@ -2223,7 +2367,7 @@ _again:
_out: {}
}
#line 1845 "upb/json/parser.rl"
#line 1970 "upb/json/parser.rl"
if (p != pe) {
upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
@ -2245,6 +2389,7 @@ bool end(void *closure, const void *hd) {
/* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_duration_machine);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
UPB_UNUSED(json_en_timestamp_machine);
@ -2254,9 +2399,9 @@ bool end(void *closure, const void *hd) {
parse(parser, hd, &eof_ch, 0, NULL);
return parser->current_state >=
#line 2258 "upb/json/parser.c"
98
#line 1874 "upb/json/parser.rl"
#line 2403 "upb/json/parser.c"
105
#line 2000 "upb/json/parser.rl"
;
}
@ -2271,13 +2416,13 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
#line 2275 "upb/json/parser.c"
#line 2420 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
#line 1888 "upb/json/parser.rl"
#line 2014 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);

@ -62,6 +62,10 @@ static bool is_boolean_wrapper_object(upb_json_parser *p);
static bool does_boolean_wrapper_start(upb_json_parser *p);
static bool does_boolean_wrapper_end(upb_json_parser *p);
static bool is_duration_object(upb_json_parser *p);
static bool does_duration_start(upb_json_parser *p);
static bool does_duration_end(upb_json_parser *p);
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);
@ -906,7 +910,7 @@ static bool start_stringval(upb_json_parser *p) {
if (is_top_level(p)) {
if (is_string_wrapper_object(p)) {
start_wrapper_object(p);
} else if (is_timestamp_object(p)) {
} else if (is_timestamp_object(p) || is_duration_object(p)) {
start_object(p);
} else {
return false;
@ -916,7 +920,7 @@ static bool start_stringval(upb_json_parser *p) {
return false;
}
start_wrapper_object(p);
} else if (does_timestamp_start(p)) {
} else if (does_timestamp_start(p) || does_duration_start(p)) {
if (!start_subobject(p)) {
return false;
}
@ -977,7 +981,7 @@ static bool start_stringval(upb_json_parser *p) {
static bool end_stringval_nontop(upb_json_parser *p) {
bool ok = true;
if (is_timestamp_object(p)) {
if (is_timestamp_object(p) || is_duration_object(p)) {
multipart_end(p);
return true;
}
@ -1058,7 +1062,7 @@ static bool end_stringval(upb_json_parser *p) {
}
}
if (does_timestamp_end(p)) {
if (does_timestamp_end(p) || does_duration_end(p)) {
end_object(p);
if (!is_top_level(p)) {
end_subobject(p);
@ -1068,6 +1072,103 @@ static bool end_stringval(upb_json_parser *p) {
return true;
}
static void start_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
static bool end_duration_base(upb_json_parser *p, const char *ptr) {
size_t len;
const char *buf;
char seconds_buf[14];
char nanos_buf[12];
char *end;
int64_t seconds = 0;
int32_t nanos = 0;
double val = 0.0;
const char *seconds_membername = "seconds";
const char *nanos_membername = "nanos";
size_t fraction_start;
if (!capture_end(p, ptr)) {
return false;
}
buf = accumulate_getptr(p, &len);
memset(seconds_buf, 0, 14);
memset(nanos_buf, 0, 12);
/* Find out base end. The maximus duration is 315576000000, which cannot be
* represented by double without losing precision. Thus, we need to handle
* fraction and base separately. */
for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
fraction_start++);
/* Parse base */
memcpy(seconds_buf, buf, fraction_start);
seconds = strtol(seconds_buf, &end, 10);
if (errno == ERANGE || end != seconds_buf + fraction_start) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
seconds_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds > 315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
"maximum acceptable value is "
"315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds < -315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
/* Parse fraction */
nanos_buf[0] = '0';
memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
nanos = val * 1000000000;
if (seconds < 0) nanos = -nanos;
/* Clean up buffer */
multipart_end(p);
/* Set seconds */
start_member(p);
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Set nanos */
start_member(p);
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
multipart_startaccum(p);
return true;
}
static void start_timestamp_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, ptr);
}
@ -1654,6 +1755,20 @@ static bool is_boolean_wrapper_object(upb_json_parser *p) {
return p->top->m != NULL && is_bool_value(p->top->m);
}
static bool does_duration_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
upb_msgdef_duration(upb_fielddef_msgsubdef(p->top->f));
}
static bool does_duration_end(upb_json_parser *p) {
return p->top->m != NULL && upb_msgdef_duration(p->top->m);
}
static bool is_duration_object(upb_json_parser *p) {
return p->top->m != NULL && upb_msgdef_duration(p->top->m);
}
static bool does_timestamp_start(upb_json_parser *p) {
return p->top->f != NULL &&
upb_fielddef_issubmsg(p->top->f) &&
@ -1738,6 +1853,14 @@ static bool is_timestamp_object(upb_json_parser *p) {
minute = digit digit;
second = digit digit;
duration_machine :=
("-"? integer decimal?)
>{ start_duration_base(parser, p); }
%{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
's"'
@{ fhold; fret; }
;
timestamp_machine :=
(year "-" month "-" day "T" hour ":" minute ":" second)
>{ start_timestamp_base(parser, p); }
@ -1757,6 +1880,8 @@ static bool is_timestamp_object(upb_json_parser *p) {
@{
if (is_timestamp_object(parser)) {
fcall timestamp_machine;
} else if (is_duration_object(parser)) {
fcall duration_machine;
} else {
fcall string_machine;
}
@ -1863,6 +1988,7 @@ bool end(void *closure, const void *hd) {
/* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_duration_machine);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
UPB_UNUSED(json_en_timestamp_machine);

@ -692,22 +692,91 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
upb_handlerattr_uninit(&empty_attr);
}
static bool puttimestamp_seconds(void *closure, const void *handler_data,
int64_t seconds) {
static bool putseconds(void *closure, const void *handler_data,
int64_t seconds) {
upb_json_printer *p = closure;
p->seconds = seconds;
UPB_UNUSED(handler_data);
return true;
}
static bool puttimestamp_nanos(void *closure, const void *handler_data,
int32_t nanos) {
static bool putnanos(void *closure, const void *handler_data,
int32_t nanos) {
upb_json_printer *p = closure;
p->nanos = nanos;
UPB_UNUSED(handler_data);
return true;
}
static bool printer_startdurationmsg(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
if (p->depth_ == 0) {
upb_bytessink_start(p->output_, 0, &p->subc_);
}
return true;
}
#define UPB_DURATION_MAX_JSON_LEN 23
#define UPB_DURATION_MAX_NANO_LEN 9
static bool printer_enddurationmsg(void *closure, const void *handler_data,
upb_status *s) {
upb_json_printer *p = closure;
char buffer[UPB_DURATION_MAX_JSON_LEN];
size_t base_len;
size_t curr;
size_t i;
memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
if (p->seconds < -315576000000) {
upb_status_seterrf(s, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
return false;
}
if (p->seconds > 315576000000) {
upb_status_seterrf(s, "error serializing duration: "
"maximum acceptable value is "
"315576000000");
return false;
}
_upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
base_len = strlen(buffer);
if (p->nanos != 0) {
char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
_upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
p->nanos / 1000000000.0);
/* Remove trailing 0. */
for (i = UPB_DURATION_MAX_NANO_LEN + 2;
nanos_buffer[i] == '0'; i--) {
nanos_buffer[i] = 0;
}
strcpy(buffer + base_len, nanos_buffer + 1);
}
curr = strlen(buffer);
strcpy(buffer + curr, "s");
p->seconds = 0;
p->nanos = 0;
print_data(p, "\"", 1);
print_data(p, buffer, strlen(buffer));
print_data(p, "\"", 1);
if (p->depth_ == 0) {
upb_bytessink_end(p->output_);
}
UPB_UNUSED(handler_data);
return true;
}
static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
@ -783,6 +852,25 @@ static bool printer_endtimestampmsg(void *closure, const void *handler_data,
return true;
}
/* Set up handlers for a duration submessage. */
void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_fielddef* seconds_field =
upb_msgdef_itof(md, UPB_DURATION_SECONDS);
const upb_fielddef* nanos_field =
upb_msgdef_itof(md, UPB_DURATION_NANOS);
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
UPB_UNUSED(closure);
}
/* Set up handlers for a timestamp submessage. Instead of printing fields
* separately, the json representation of timestamp follows RFC 3339 */
void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
@ -796,8 +884,8 @@ void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
upb_handlers_setint64(h, seconds_field, puttimestamp_seconds, &empty_attr);
upb_handlers_setint32(h, nanos_field, puttimestamp_nanos, &empty_attr);
upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
UPB_UNUSED(closure);
@ -818,6 +906,11 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
return;
}
if (upb_msgdef_duration(md)) {
printer_sethandlers_duration(closure, h);
return;
}
if (upb_msgdef_timestamp(md)) {
printer_sethandlers_timestamp(closure, h);
return;

Loading…
Cancel
Save