summaryrefslogtreecommitdiff
path: root/upb/json
diff options
context:
space:
mode:
Diffstat (limited to 'upb/json')
-rw-r--r--upb/json/parser.c598
-rw-r--r--upb/json/parser.h164
-rw-r--r--upb/json/parser.rl482
-rw-r--r--upb/json/printer.c88
-rw-r--r--upb/json/printer.h85
5 files changed, 669 insertions, 748 deletions
diff --git a/upb/json/parser.c b/upb/json/parser.c
index f15a95e..d8db7fe 100644
--- a/upb/json/parser.c
+++ b/upb/json/parser.c
@@ -24,6 +24,7 @@
/* Need to define _XOPEN_SOURCE before any include to make strptime work. */
#define _XOPEN_SOURCE 700
+#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <math.h>
@@ -62,7 +63,6 @@ static bool is_string_wrapper_object(upb_json_parser *p);
static bool does_string_wrapper_start(upb_json_parser *p);
static bool does_string_wrapper_end(upb_json_parser *p);
-static bool is_fieldmask_object(upb_json_parser *p);
static bool does_fieldmask_start(upb_json_parser *p);
static bool does_fieldmask_end(upb_json_parser *p);
static void start_fieldmask_object(upb_json_parser *p);
@@ -159,14 +159,13 @@ void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
typedef struct {
/* For encoding Any value field in binary format. */
- const upb_handlers *encoder_handlers;
- upb_pb_encoder *encoder;
+ upb_handlercache *encoder_handlercache;
upb_stringsink stringsink;
/* For decoding Any value field in json format. */
- upb_json_parsermethod *parser_method;
- upb_json_parser* parser;
+ upb_json_codecache *parser_codecache;
upb_sink sink;
+ upb_json_parser *parser;
/* Mark the range of uninterpreted values in json input before type url. */
const char *before_type_url_start;
@@ -185,7 +184,7 @@ typedef struct {
const upb_fielddef *f;
/* The table mapping json name to fielddef for this message. */
- upb_strtable *name_table;
+ const upb_strtable *name_table;
/* We are in a repeated-field context, ready to emit mapentries as
* submessages. This flag alters the start-of-object (open-brace) behavior to
@@ -218,7 +217,7 @@ typedef struct {
} upb_jsonparser_frame;
struct upb_json_parser {
- upb_env *env;
+ upb_arena *arena;
const upb_json_parsermethod *method;
upb_bytessink input_;
@@ -227,7 +226,7 @@ struct upb_json_parser {
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
- upb_status status;
+ upb_status *status;
/* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
@@ -264,64 +263,68 @@ struct upb_json_parser {
struct tm tm;
};
-struct upb_json_parsermethod {
- upb_refcounted base;
+struct upb_json_codecache {
+ upb_arena *arena;
+ upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */
+};
+struct upb_json_parsermethod {
+ const upb_json_codecache *cache;
upb_byteshandler input_handler_;
- /* Mainly for the purposes of refcounting, so all the fielddefs we point
- * to stay alive. */
- const upb_msgdef *msg;
-
- /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
- upb_inttable name_tables;
+ /* Maps json_name -> fielddef */
+ upb_strtable name_table;
};
#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-static void json_parser_any_frame_reset(upb_jsonparser_any_frame *frame) {
- frame->encoder_handlers = NULL;
- frame->encoder = NULL;
- frame->parser_method = NULL;
+static upb_jsonparser_any_frame *json_parser_any_frame_new(
+ upb_json_parser *p) {
+ upb_jsonparser_any_frame *frame;
+
+ frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
+
+ frame->encoder_handlercache = upb_pb_encoder_newcache();
+ frame->parser_codecache = upb_json_codecache_new();
frame->parser = NULL;
frame->before_type_url_start = NULL;
frame->before_type_url_end = NULL;
frame->after_type_url_start = NULL;
+
+ upb_stringsink_init(&frame->stringsink);
+
+ return frame;
}
static void json_parser_any_frame_set_payload_type(
upb_json_parser *p,
upb_jsonparser_any_frame *frame,
const upb_msgdef *payload_type) {
+ const upb_handlers *h;
+ const upb_json_parsermethod *parser_method;
+ upb_pb_encoder *encoder;
+
/* Initialize encoder. */
- frame->encoder_handlers =
- upb_pb_encoder_newhandlers(payload_type, &frame->encoder_handlers);
- upb_stringsink_init(&frame->stringsink);
- frame->encoder =
- upb_pb_encoder_create(
- p->env, frame->encoder_handlers,
- &frame->stringsink.sink);
+ h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
+ encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
/* Initialize parser. */
- frame->parser_method =
- upb_json_parsermethod_new(payload_type, &frame->parser_method);
- upb_sink_reset(&frame->sink, frame->encoder_handlers, frame->encoder);
+ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
+ upb_sink_reset(&frame->sink, h, encoder);
frame->parser =
- upb_json_parser_create(p->env, frame->parser_method, p->symtab,
- &frame->sink, p->ignore_json_unknown);
+ upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
+ p->status, p->ignore_json_unknown);
}
static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
- upb_handlers_unref(frame->encoder_handlers,
- &frame->encoder_handlers);
- upb_json_parsermethod_unref(frame->parser_method,
- &frame->parser_method);
+ upb_handlercache_free(frame->encoder_handlercache);
+ upb_json_codecache_free(frame->parser_codecache);
upb_stringsink_uninit(&frame->stringsink);
}
static bool json_parser_any_frame_has_type_url(
upb_jsonparser_any_frame *frame) {
- return frame->encoder != NULL;
+ return frame->parser != NULL;
}
static bool json_parser_any_frame_has_value_before_type_url(
@@ -343,7 +346,7 @@ static bool json_parser_any_frame_has_value(
static void json_parser_any_frame_set_before_type_url_end(
upb_jsonparser_any_frame *frame,
const char *ptr) {
- if (frame->encoder == NULL) {
+ if (frame->parser == NULL) {
frame->before_type_url_end = ptr;
}
}
@@ -375,8 +378,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) {
static bool check_stack(upb_json_parser *p) {
if ((p->top + 1) == p->limit) {
- upb_status_seterrmsg(&p->status, "Nesting too deep");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Nesting too deep");
return false;
}
@@ -385,9 +387,15 @@ static bool check_stack(upb_json_parser *p) {
static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
upb_value v;
- bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
+ const upb_json_codecache *cache = p->method->cache;
+ bool ok;
+ const upb_json_parsermethod *method;
+
+ ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
UPB_ASSERT(ok);
- frame->name_table = upb_value_getptr(v);
+ method = upb_value_getconstptr(v);
+
+ frame->name_table = &method->name_table;
}
/* There are GCC/Clang built-ins for overflow checking which we could start
@@ -465,10 +473,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
char output[3];
if (limit - ptr < 4) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -485,17 +492,16 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
output[2] = val & 0xff;
- upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
+ upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
}
return true;
otherchar:
if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
nonbase64(ptr[3]) ) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Non-base64 characters in bytes field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
} if (ptr[2] == '=') {
uint32_t val;
@@ -511,7 +517,7 @@ otherchar:
UPB_ASSERT(!(val & 0x80000000));
output = val >> 16;
- upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
return true;
} else {
uint32_t val;
@@ -528,16 +534,15 @@ otherchar:
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
- upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
+ upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
return true;
}
badpadding:
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Incorrect base64 padding for field: %s (%.*s)",
upb_fielddef_name(p->top->f),
4, ptr);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -581,10 +586,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
new_size = saturating_multiply(new_size, 2);
}
- mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+ mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
if (!mem) {
- upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
}
@@ -607,8 +611,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
}
if (!checked_add(p->accumulated_len, len, &need)) {
- upb_status_seterrmsg(&p->status, "Integer overflow.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
}
@@ -686,8 +689,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
switch (p->multipart_state) {
case MULTIPART_INACTIVE:
upb_status_seterrmsg(
- &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
return false;
case MULTIPART_ACCUMULATE:
@@ -698,7 +700,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
case MULTIPART_PUSHEAGERLY: {
const upb_bufhandle *handle = can_alias ? p->handle : NULL;
- upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
+ upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
break;
}
}
@@ -944,7 +946,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (val > INT32_MAX || val < INT32_MIN) {
return false;
} else {
- upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -955,7 +957,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (val > UINT32_MAX || errno == ERANGE) {
return false;
} else {
- upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putuint32(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -966,7 +968,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
if (errno == ERANGE || end != bufend) {
break;
} else {
- upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -977,7 +979,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (errno == ERANGE) {
return false;
} else {
- upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -1008,7 +1010,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
if (modf(val, &dummy) != 0 || val > max || val < min) { \
return false; \
} else { \
- upb_sink_put ## smalltype(&p->top->sink, parser_getsel(p), \
+ upb_sink_put ## smalltype(p->top->sink, parser_getsel(p), \
(ctype)val); \
return true; \
} \
@@ -1022,13 +1024,13 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
#undef CASE
case UPB_TYPE_DOUBLE:
- upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
return true;
case UPB_TYPE_FLOAT:
if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
return false;
} else {
- upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
return true;
}
default:
@@ -1052,8 +1054,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) {
multipart_end(p);
return true;
} else {
- upb_status_seterrf(&p->status, "error parsing number: %s", buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing number: %s", buf);
multipart_end(p);
return false;
}
@@ -1067,14 +1068,13 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
}
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
- ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+ ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
UPB_ASSERT(ok);
return true;
@@ -1223,7 +1223,7 @@ static bool start_stringval(upb_json_parser *p) {
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
@@ -1254,10 +1254,9 @@ static bool start_stringval(upb_json_parser *p) {
multipart_startaccum(p);
return true;
} else {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"String specified for bool or submessage field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
}
@@ -1273,11 +1272,11 @@ static bool end_any_stringval(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&inner->sink, sel, buf, len, NULL);
+ upb_sink_putstring(inner->sink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&inner->sink, sel);
+ upb_sink_endstr(inner->sink, sel);
multipart_end(p);
@@ -1290,18 +1289,16 @@ static bool end_any_stringval(upb_json_parser *p) {
payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
if (payload_type == NULL) {
upb_status_seterrf(
- &p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
return false;
}
json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
+
return true;
} else {
upb_status_seterrf(
- &p->status, "Invalid type url: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Invalid type url: %.*s\n", (int)len, buf);
return false;
}
}
@@ -1334,15 +1331,14 @@ static bool end_stringval_nontop(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
+ upb_sink_endstr(p->top->sink, sel);
p->top--;
break;
}
case UPB_TYPE_ENUM: {
/* Resolve enum symbolic name to integer value. */
- const upb_enumdef *enumdef =
- (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
+ const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
size_t len;
const char *buf = accumulate_getptr(p, &len);
@@ -1352,10 +1348,9 @@ static bool end_stringval_nontop(upb_json_parser *p) {
if (ok) {
upb_selector_t sel = parser_getsel(p);
- upb_sink_putint32(&p->top->sink, sel, int_val);
+ upb_sink_putint32(p->top->sink, sel, int_val);
} else {
- upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
}
break;
@@ -1372,8 +1367,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
default:
UPB_ASSERT(false);
- upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
ok = false;
break;
}
@@ -1463,25 +1457,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
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",
+ 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: "
+ 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: "
+ upb_status_seterrf(p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1490,9 +1481,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
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",
+ upb_status_seterrf(p->status, "error parsing duration: %s",
nanos_buf);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1507,7 +1497,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
- upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Set nanos */
@@ -1515,10 +1505,10 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
- upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
end_member(p);
- /* Continue previous environment */
+ /* Continue previous arena */
multipart_startaccum(p);
return true;
@@ -1547,15 +1537,13 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) {
timestamp_buf[UPB_TIMESTAMP_BASE_SIZE + 3] = 0;
#if defined __MINGW32__ || defined __MINGW64__
- upb_status_seterrf(
- &p->status, "error parsing timestamp: mingw doesn't support strptime");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status,
+ "error parsing timestamp: mingw doesn't support strptime");
return false;
#else
/* Parse seconds */
if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) {
- upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing timestamp: %s", buf);
return false;
}
#endif
@@ -1589,9 +1577,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
buf = accumulate_getptr(p, &len);
if (len > 10) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"error parsing timestamp: at most 9-digit fraction.");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1601,9 +1588,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len + 1) {
- upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s",
+ upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
nanos_buf);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1617,7 +1603,7 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
- upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
@@ -1645,8 +1631,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
if (buf[0] != 'Z') {
if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
- upb_status_seterrf(&p->status, "error parsing timestamp offset");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing timestamp offset");
return false;
}
@@ -1662,10 +1647,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
/* Check timestamp boundary */
if (seconds < -62135596800) {
- upb_status_seterrf(&p->status, "error parsing timestamp: "
+ upb_status_seterrf(p->status, "error parsing timestamp: "
"minimum acceptable value is "
"0001-01-01T00:00:00Z");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1677,7 +1661,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
- upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Continue previous environment */
@@ -1691,9 +1675,7 @@ static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
}
static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
+ return capture_end(p, ptr);
}
static bool start_fieldmask_path(upb_json_parser *p) {
@@ -1706,7 +1688,7 @@ static bool start_fieldmask_path(upb_json_parser *p) {
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
@@ -1728,10 +1710,10 @@ static bool lower_camel_push(
for (;ptr < limit; ptr++) {
if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
char lower = tolower(*ptr);
- upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL);
- upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
} else {
- upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
}
first = false;
}
@@ -1748,7 +1730,7 @@ static bool end_fieldmask_path(upb_json_parser *p) {
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
+ upb_sink_endstr(p->top->sink, sel);
p->top--;
multipart_end(p);
@@ -1775,8 +1757,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
- upb_status_seterrmsg(&p->status, "mapentry message has no key");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "mapentry message has no key");
return false;
}
switch (upb_fielddef_type(p->top->f)) {
@@ -1799,9 +1780,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return false;
}
} else {
- upb_status_seterrmsg(&p->status,
+ upb_status_seterrmsg(p->status,
"Map bool key not 'true' or 'false'");
- upb_env_reporterror(p->env, &p->status);
return false;
}
multipart_end(p);
@@ -1810,17 +1790,16 @@ static bool parse_mapentry_key(upb_json_parser *p) {
case UPB_TYPE_BYTES: {
upb_sink subsink;
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, len, &subsink);
+ upb_sink_startstr(p->top->sink, sel, len, &subsink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&subsink, sel, buf, len, NULL);
+ upb_sink_putstring(subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&subsink, sel);
+ upb_sink_endstr(subsink, sel);
multipart_end(p);
break;
}
default:
- upb_status_seterrmsg(&p->status, "Invalid field type for map key");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Invalid field type for map key");
return false;
}
@@ -1853,7 +1832,7 @@ static bool handle_mapentry(upb_json_parser *p) {
inner = p->top + 1;
p->top->f = mapfield;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+ upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
inner->m = mapentrymsg;
inner->name_table = NULL;
inner->mapfield = mapfield;
@@ -1870,7 +1849,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top = inner;
/* send STARTMSG in submsg frame. */
- upb_sink_startmsg(&p->top->sink);
+ upb_sink_startmsg(p->top->sink);
parse_mapentry_key(p);
@@ -1879,8 +1858,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
p->top->mapfield = mapfield;
if (p->top->f == NULL) {
- upb_status_seterrmsg(&p->status, "mapentry message has no value");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "mapentry message has no value");
return false;
}
@@ -1915,8 +1893,7 @@ static bool end_membername(upb_json_parser *p) {
multipart_end(p);
return true;
} else {
- upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
}
@@ -1942,21 +1919,20 @@ static bool end_any_membername(upb_json_parser *p) {
static void end_member(upb_json_parser *p) {
/* If we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
- upb_status s = UPB_STATUS_INIT;
upb_selector_t sel;
bool ok;
const upb_fielddef *mapfield;
UPB_ASSERT(p->top > p->stack);
/* send ENDMSG on submsg. */
- upb_sink_endmsg(&p->top->sink, &s);
+ upb_sink_endmsg(p->top->sink, p->status);
mapfield = p->top->mapfield;
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--;
ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT(ok);
- upb_sink_endsubmsg(&p->top->sink, sel);
+ upb_sink_endsubmsg(p->top->sink, sel);
}
p->top->f = NULL;
@@ -2000,7 +1976,7 @@ static bool start_subobject(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+ upb_sink_startseq(p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->name_table = NULL;
inner->mapfield = p->top->f;
@@ -2024,7 +2000,7 @@ static bool start_subobject(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+ upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
set_name_table(p, inner);
inner->f = NULL;
@@ -2035,9 +2011,7 @@ static bool start_subobject(upb_json_parser *p) {
if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
p->top->is_any = true;
- p->top->any_frame =
- upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
- json_parser_any_frame_reset(p->top->any_frame);
+ p->top->any_frame = json_parser_any_frame_new(p);
} else {
p->top->is_any = false;
p->top->any_frame = NULL;
@@ -2045,10 +2019,9 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Object specified for non-message/group field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
}
@@ -2086,14 +2059,14 @@ static void end_subobject(upb_json_parser *p) {
upb_selector_t sel;
p->top--;
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(&p->top->sink, sel);
+ upb_sink_endseq(p->top->sink, sel);
} else {
upb_selector_t sel;
bool is_unknown = p->top->m == NULL;
p->top--;
if (!is_unknown) {
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
- upb_sink_endsubmsg(&p->top->sink, sel);
+ upb_sink_endsubmsg(p->top->sink, sel);
}
}
}
@@ -2156,10 +2129,9 @@ static bool start_array(upb_json_parser *p) {
}
if (!upb_fielddef_isseq(p->top->f)) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Array specified for non-repeated field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -2167,7 +2139,7 @@ static bool start_array(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+ upb_sink_startseq(p->top->sink, sel, &inner->sink);
inner->m = p->top->m;
inner->name_table = NULL;
inner->f = p->top->f;
@@ -2193,7 +2165,7 @@ static void end_array(upb_json_parser *p) {
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(&p->top->sink, sel);
+ upb_sink_endseq(p->top->sink, sel);
if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
end_listvalue_object(p);
@@ -2212,18 +2184,13 @@ static void end_array(upb_json_parser *p) {
static void start_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
- upb_sink_startmsg(&p->top->sink);
+ upb_sink_startmsg(p->top->sink);
}
}
static void end_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
- upb_status status;
- upb_status_clear(&status);
- upb_sink_endmsg(&p->top->sink, &status);
- if (!upb_ok(&status)) {
- upb_env_reporterror(p->env, &status);
- }
+ upb_sink_endmsg(p->top->sink, p->status);
}
}
@@ -2242,8 +2209,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
if (json_parser_any_frame_has_value(p->top->any_frame) &&
!json_parser_any_frame_has_type_url(p->top->any_frame)) {
- upb_status_seterrmsg(&p->status, "No valid type url");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "No valid type url");
return false;
}
@@ -2258,8 +2224,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
p->top->any_frame->before_type_url_end -
p->top->any_frame->before_type_url_start);
if (p->top->any_frame->before_type_url_start == NULL) {
- upb_status_seterrmsg(&p->status, "invalid data for well known type.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "invalid data for well known type.");
return false;
}
p->top->any_frame->before_type_url_start++;
@@ -2271,8 +2236,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
(ptr + 1) -
p->top->any_frame->after_type_url_start);
if (p->top->any_frame->after_type_url_start == NULL) {
- upb_status_seterrmsg(&p->status, "Invalid data for well known type.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Invalid data for well known type.");
return false;
}
p->top->any_frame->after_type_url_start++;
@@ -2332,12 +2296,12 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&inner->sink, sel, p->top->any_frame->stringsink.ptr,
+ upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
p->top->any_frame->stringsink.len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&inner->sink, sel);
+ upb_sink_endstr(inner->sink, sel);
end_member(p);
@@ -2345,7 +2309,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
/* Deallocate any parse frame. */
json_parser_any_frame_free(p->top->any_frame);
- upb_env_free(p->env, p->top->any_frame);
return true;
}
@@ -2529,10 +2492,6 @@ static bool does_fieldmask_end(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
-static bool is_fieldmask_object(upb_json_parser *p) {
- return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
#define CHECK_RETURN_TOP(x) if (!(x)) goto error
@@ -2554,11 +2513,11 @@ static bool is_fieldmask_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
-#line 2736 "upb/json/parser.rl"
+#line 2695 "upb/json/parser.rl"
-#line 2562 "upb/json/parser.c"
+#line 2521 "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,
@@ -2810,7 +2769,7 @@ static const int json_en_value_machine = 78;
static const int json_en_main = 1;
-#line 2739 "upb/json/parser.rl"
+#line 2698 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@@ -2833,7 +2792,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
-#line 2837 "upb/json/parser.c"
+#line 2796 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@@ -2908,103 +2867,103 @@ _match:
switch ( *_acts++ )
{
case 1:
-#line 2567 "upb/json/parser.rl"
+#line 2526 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 2:
-#line 2569 "upb/json/parser.rl"
+#line 2528 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
break;
case 3:
-#line 2573 "upb/json/parser.rl"
+#line 2532 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 4:
-#line 2574 "upb/json/parser.rl"
+#line 2533 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 5:
-#line 2580 "upb/json/parser.rl"
+#line 2539 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 6:
-#line 2581 "upb/json/parser.rl"
+#line 2540 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 7:
-#line 2582 "upb/json/parser.rl"
+#line 2541 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 8:
-#line 2588 "upb/json/parser.rl"
+#line 2547 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 9:
-#line 2594 "upb/json/parser.rl"
+#line 2553 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 10:
-#line 2606 "upb/json/parser.rl"
+#line 2565 "upb/json/parser.rl"
{ start_duration_base(parser, p); }
break;
case 11:
-#line 2607 "upb/json/parser.rl"
+#line 2566 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break;
case 12:
-#line 2609 "upb/json/parser.rl"
+#line 2568 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 13:
-#line 2614 "upb/json/parser.rl"
+#line 2573 "upb/json/parser.rl"
{ start_timestamp_base(parser, p); }
break;
case 14:
-#line 2615 "upb/json/parser.rl"
+#line 2574 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_base(parser, p)); }
break;
case 15:
-#line 2617 "upb/json/parser.rl"
+#line 2576 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
break;
case 16:
-#line 2618 "upb/json/parser.rl"
+#line 2577 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break;
case 17:
-#line 2620 "upb/json/parser.rl"
+#line 2579 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
break;
case 18:
-#line 2621 "upb/json/parser.rl"
+#line 2580 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break;
case 19:
-#line 2623 "upb/json/parser.rl"
+#line 2582 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 20:
-#line 2628 "upb/json/parser.rl"
+#line 2587 "upb/json/parser.rl"
{ start_fieldmask_path_text(parser, p); }
break;
case 21:
-#line 2629 "upb/json/parser.rl"
+#line 2588 "upb/json/parser.rl"
{ end_fieldmask_path_text(parser, p); }
break;
case 22:
-#line 2634 "upb/json/parser.rl"
+#line 2593 "upb/json/parser.rl"
{ start_fieldmask_path(parser); }
break;
case 23:
-#line 2635 "upb/json/parser.rl"
+#line 2594 "upb/json/parser.rl"
{ end_fieldmask_path(parser); }
break;
case 24:
-#line 2641 "upb/json/parser.rl"
+#line 2600 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 25:
-#line 2646 "upb/json/parser.rl"
+#line 2605 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
{stack[top++] = cs; cs = 47;goto _again;}
@@ -3018,11 +2977,11 @@ _match:
}
break;
case 26:
-#line 2659 "upb/json/parser.rl"
+#line 2618 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
break;
case 27:
-#line 2664 "upb/json/parser.rl"
+#line 2623 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_member(parser, p);
@@ -3032,11 +2991,11 @@ _match:
}
break;
case 28:
-#line 2671 "upb/json/parser.rl"
+#line 2630 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 29:
-#line 2674 "upb/json/parser.rl"
+#line 2633 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
end_any_member(parser, p);
@@ -3046,7 +3005,7 @@ _match:
}
break;
case 30:
-#line 2685 "upb/json/parser.rl"
+#line 2644 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_object(parser, p);
@@ -3056,7 +3015,7 @@ _match:
}
break;
case 31:
-#line 2694 "upb/json/parser.rl"
+#line 2653 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
CHECK_RETURN_TOP(end_any_object(parser, p));
@@ -3066,54 +3025,54 @@ _match:
}
break;
case 32:
-#line 2706 "upb/json/parser.rl"
+#line 2665 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 33:
-#line 2710 "upb/json/parser.rl"
+#line 2669 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 34:
-#line 2715 "upb/json/parser.rl"
+#line 2674 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); }
break;
case 35:
-#line 2716 "upb/json/parser.rl"
+#line 2675 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 36:
-#line 2718 "upb/json/parser.rl"
+#line 2677 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 37:
-#line 2719 "upb/json/parser.rl"
+#line 2678 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 38:
-#line 2721 "upb/json/parser.rl"
+#line 2680 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 39:
-#line 2723 "upb/json/parser.rl"
+#line 2682 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 40:
-#line 2725 "upb/json/parser.rl"
+#line 2684 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 41:
-#line 2727 "upb/json/parser.rl"
+#line 2686 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
break;
case 42:
-#line 2728 "upb/json/parser.rl"
+#line 2687 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
case 43:
-#line 2733 "upb/json/parser.rl"
+#line 2692 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
-#line 3117 "upb/json/parser.c"
+#line 3076 "upb/json/parser.c"
}
}
@@ -3130,32 +3089,32 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 0:
-#line 2565 "upb/json/parser.rl"
+#line 2524 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; if ( p == pe )
goto _test_eof;
goto _again;} }
break;
case 35:
-#line 2716 "upb/json/parser.rl"
+#line 2675 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 38:
-#line 2721 "upb/json/parser.rl"
+#line 2680 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 39:
-#line 2723 "upb/json/parser.rl"
+#line 2682 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 40:
-#line 2725 "upb/json/parser.rl"
+#line 2684 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 42:
-#line 2728 "upb/json/parser.rl"
+#line 2687 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
-#line 3159 "upb/json/parser.c"
+#line 3118 "upb/json/parser.c"
}
}
}
@@ -3163,11 +3122,10 @@ goto _again;} }
_out: {}
}
-#line 2761 "upb/json/parser.rl"
+#line 2720 "upb/json/parser.rl"
if (p != pe) {
- upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
- upb_env_reporterror(parser->env, &parser->status);
+ upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
} else {
capture_suspend(parser, &p);
}
@@ -3212,123 +3170,91 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
-#line 3216 "upb/json/parser.c"
+#line 3174 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
-#line 2809 "upb/json/parser.rl"
+#line 2767 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);
p->multipart_state = MULTIPART_INACTIVE;
p->capture = NULL;
p->accumulated = NULL;
- upb_status_clear(&p->status);
}
-static void visit_json_parsermethod(const upb_refcounted *r,
- upb_refcounted_visit *visit,
- void *closure) {
- const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
- visit(r, upb_msgdef_upcast2(method->msg), closure);
-}
-
-static void free_json_parsermethod(upb_refcounted *r) {
- upb_json_parsermethod *method = (upb_json_parsermethod*)r;
-
- upb_inttable_iter i;
- upb_inttable_begin(&i, &method->name_tables);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_value val = upb_inttable_iter_value(&i);
- upb_strtable *t = upb_value_getptr(val);
- upb_strtable_uninit(t);
- upb_gfree(t);
- }
+static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
+ const upb_msgdef *md) {
+ upb_msg_field_iter i;
+ upb_alloc *alloc = upb_arena_alloc(c->arena);
- upb_inttable_uninit(&method->name_tables);
+ upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
- upb_gfree(r);
-}
-
-static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
- upb_msg_field_iter i;
- upb_strtable *t;
+ m->cache = c;
- /* It would be nice to stack-allocate this, but protobufs do not limit the
- * length of fields to any reasonable limit. */
- char *buf = NULL;
- size_t len = 0;
+ upb_byteshandler_init(&m->input_handler_);
+ upb_byteshandler_setstring(&m->input_handler_, parse, m);
+ upb_byteshandler_setendstr(&m->input_handler_, end, m);
- if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
- return;
- }
+ upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
- /* TODO(haberman): handle malloc failure. */
- t = upb_gmalloc(sizeof(*t));
- upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
- upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
+ /* Build name_table */
for(upb_msg_field_begin(&i, md);
!upb_msg_field_done(&i);
upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
+ upb_value v = upb_value_constptr(f);
+ char *buf;
/* Add an entry for the JSON name. */
- size_t field_len = upb_fielddef_getjsonname(f, buf, len);
- if (field_len > len) {
- size_t len2;
- buf = upb_grealloc(buf, 0, field_len);
- len = field_len;
- len2 = upb_fielddef_getjsonname(f, buf, len);
- UPB_ASSERT(len == len2);
- }
- upb_strtable_insert(t, buf, upb_value_constptr(f));
+ size_t len = upb_fielddef_getjsonname(f, NULL, 0);
+ buf = upb_malloc(alloc, len);
+ upb_fielddef_getjsonname(f, buf, len);
+ upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc);
if (strcmp(buf, upb_fielddef_name(f)) != 0) {
/* Since the JSON name is different from the regular field name, add an
* entry for the raw name (compliant proto3 JSON parsers must accept
* both). */
- upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
- }
-
- if (upb_fielddef_issubmsg(f)) {
- add_jsonname_table(m, upb_fielddef_msgsubdef(f));
+ const char *name = upb_fielddef_name(f);
+ upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
}
}
- upb_gfree(buf);
+ return m;
}
/* Public API *****************************************************************/
-upb_json_parser *upb_json_parser_create(upb_env *env,
+upb_json_parser *upb_json_parser_create(upb_arena *arena,
const upb_json_parsermethod *method,
const upb_symtab* symtab,
- upb_sink *output,
+ upb_sink output,
+ upb_status *status,
bool ignore_json_unknown) {
#ifndef NDEBUG
- const size_t size_before = upb_env_bytesallocated(env);
+ const size_t size_before = upb_arena_bytesallocated(arena);
#endif
- upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
+ upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
if (!p) return false;
- p->env = env;
+ p->arena = arena;
p->method = method;
+ p->status = status;
p->limit = p->stack + UPB_JSON_MAX_DEPTH;
p->accumulate_buf = NULL;
p->accumulate_buf_size = 0;
upb_bytessink_reset(&p->input_, &method->input_handler_, p);
json_parser_reset(p);
- upb_sink_reset(&p->top->sink, output->handlers, output->closure);
- p->top->m = upb_handlers_msgdef(output->handlers);
+ p->top->sink = output;
+ p->top->m = upb_handlers_msgdef(output.handlers);
if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
p->top->is_any = true;
- p->top->any_frame =
- upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
- json_parser_any_frame_reset(p->top->any_frame);
+ p->top->any_frame = json_parser_any_frame_new(p);
} else {
p->top->is_any = false;
p->top->any_frame = NULL;
@@ -3339,38 +3265,72 @@ upb_json_parser *upb_json_parser_create(upb_env *env,
p->ignore_json_unknown = ignore_json_unknown;
/* If this fails, uncomment and increase the value in parser.h. */
- /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
- UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
+ /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
+ UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
UPB_JSON_PARSER_SIZE);
return p;
}
-upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
- return &p->input_;
+upb_bytessink upb_json_parser_input(upb_json_parser *p) {
+ return p->input_;
}
-upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
- const void* owner) {
- static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
- free_json_parsermethod};
- upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret));
- upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+ const upb_json_parsermethod *m) {
+ return &m->input_handler_;
+}
- ret->msg = md;
- upb_ref2(md, ret);
+upb_json_codecache *upb_json_codecache_new() {
+ upb_alloc *alloc;
+ upb_json_codecache *c;
- upb_byteshandler_init(&ret->input_handler_);
- upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
- upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
+ c = upb_gmalloc(sizeof(*c));
- upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
+ c->arena = upb_arena_new();
+ alloc = upb_arena_alloc(c->arena);
- add_jsonname_table(ret, md);
+ upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
- return ret;
+ return c;
}
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
- const upb_json_parsermethod *m) {
- return &m->input_handler_;
+void upb_json_codecache_free(upb_json_codecache *c) {
+ upb_arena_free(c->arena);
+ upb_gfree(c);
+}
+
+const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
+ const upb_msgdef *md) {
+ upb_json_parsermethod *m;
+ upb_value v;
+ upb_msg_field_iter i;
+ upb_alloc *alloc = upb_arena_alloc(c->arena);
+
+ if (upb_inttable_lookupptr(&c->methods, md, &v)) {
+ return upb_value_getconstptr(v);
+ }
+
+ m = parsermethod_new(c, md);
+ v = upb_value_constptr(m);
+
+ if (!m) return NULL;
+ if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
+
+ /* Populate parser methods for all submessages, so the name tables will
+ * be available during parsing. */
+ for(upb_msg_field_begin(&i, md);
+ !upb_msg_field_done(&i);
+ upb_msg_field_next(&i)) {
+ upb_fielddef *f = upb_msg_iter_field(&i);
+
+ if (upb_fielddef_issubmsg(f)) {
+ const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
+ const upb_json_parsermethod *sub_method =
+ upb_json_codecache_get(c, subdef);
+
+ if (!sub_method) return NULL;
+ }
+ }
+
+ return m;
}
diff --git a/upb/json/parser.h b/upb/json/parser.h
index fb5fd2f..c063a77 100644
--- a/upb/json/parser.h
+++ b/upb/json/parser.h
@@ -13,17 +13,46 @@
#ifdef __cplusplus
namespace upb {
namespace json {
-class Parser;
-class ParserMethod;
+class CodeCache;
+class ParserPtr;
+class ParserMethodPtr;
} /* namespace json */
} /* namespace upb */
#endif
-UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
-UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted,
- upb_json_parsermethod, upb_refcounted)
+/* upb_json_parsermethod ******************************************************/
-/* upb::json::Parser **********************************************************/
+struct upb_json_parsermethod;
+typedef struct upb_json_parsermethod upb_json_parsermethod;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_byteshandler* upb_json_parsermethod_inputhandler(
+ const upb_json_parsermethod* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+
+class upb::json::ParserMethodPtr {
+ public:
+ ParserMethodPtr() : ptr_(nullptr) {}
+ ParserMethodPtr(const upb_json_parsermethod* ptr) : ptr_(ptr) {}
+
+ const upb_json_parsermethod* ptr() const { return ptr_; }
+
+ const BytesHandler* input_handler() const {
+ return upb_json_parsermethod_inputhandler(ptr());
+ }
+
+ private:
+ const upb_json_parsermethod* ptr_;
+};
+
+#endif /* __cplusplus */
+
+/* upb_json_parser ************************************************************/
/* Preallocation hint: parser won't allocate more bytes than this when first
* constructed. This hint may be an overestimate for some build configurations.
@@ -31,96 +60,81 @@ UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted,
* it may be an underestimate. */
#define UPB_JSON_PARSER_SIZE 5712
-#ifdef __cplusplus
+struct upb_json_parser;
+typedef struct upb_json_parser upb_json_parser;
-/* Parses an incoming BytesStream, pushing the results to the destination
- * sink. */
-class upb::json::Parser {
- public:
- static Parser* Create(Environment* env, const ParserMethod* method,
- const SymbolTable* symtab,
- Sink* output, bool ignore_json_unknown);
+#ifdef __cplusplus
+extern "C" {
+#endif
- BytesSink* input();
+upb_json_parser* upb_json_parser_create(upb_arena* a,
+ const upb_json_parsermethod* m,
+ const upb_symtab* symtab,
+ upb_sink output,
+ upb_status *status,
+ bool ignore_json_unknown);
+upb_bytessink upb_json_parser_input(upb_json_parser* p);
- private:
- UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser)
-};
+#ifdef __cplusplus
+} /* extern "C" */
-class upb::json::ParserMethod {
+/* Parses an incoming BytesStream, pushing the results to the destination
+ * sink. */
+class upb::json::ParserPtr {
public:
- /* Include base methods from upb::ReferenceCounted. */
- UPB_REFCOUNTED_CPPMETHODS
+ ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {}
- /* Returns handlers for parsing according to the specified schema. */
- static reffed_ptr<const ParserMethod> New(const upb::MessageDef* md);
+ static ParserPtr Create(Arena* arena, ParserMethodPtr method,
+ SymbolTable* symtab, Sink output, Status* status,
+ bool ignore_json_unknown) {
+ upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr;
+ return ParserPtr(upb_json_parser_create(
+ arena->ptr(), method.ptr(), symtab_ptr, output.sink(), status->ptr(),
+ ignore_json_unknown));
+ }
- /* The destination handlers that are statically bound to this method.
- * This method is only capable of outputting to a sink that uses these
- * handlers. */
- const Handlers* dest_handlers() const;
-
- /* The input handlers for this decoder method. */
- const BytesHandler* input_handler() const;
+ BytesSink input() { return upb_json_parser_input(ptr_); }
private:
- UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod)
+ upb_json_parser* ptr_;
};
-#endif
+#endif /* __cplusplus */
-UPB_BEGIN_EXTERN_C
+/* upb_json_codecache *********************************************************/
-upb_json_parser* upb_json_parser_create(upb_env* e,
- const upb_json_parsermethod* m,
- const upb_symtab* symtab,
- upb_sink* output,
- bool ignore_json_unknown);
-upb_bytessink *upb_json_parser_input(upb_json_parser *p);
+/* Lazily builds and caches decoder methods that will push data to the given
+ * handlers. The upb_symtab object(s) must outlive this object. */
-upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md,
- const void* owner);
-const upb_handlers *upb_json_parsermethod_desthandlers(
- const upb_json_parsermethod *m);
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
- const upb_json_parsermethod *m);
+struct upb_json_codecache;
+typedef struct upb_json_codecache upb_json_codecache;
-/* Include refcounted methods like upb_json_parsermethod_ref(). */
-UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast)
+#ifdef __cplusplus
+extern "C" {
+#endif
-UPB_END_EXTERN_C
+upb_json_codecache *upb_json_codecache_new();
+void upb_json_codecache_free(upb_json_codecache *cache);
+const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache,
+ const upb_msgdef* md);
#ifdef __cplusplus
+} /* extern "C" */
-namespace upb {
-namespace json {
-inline Parser* Parser::Create(Environment* env, const ParserMethod* method,
- const SymbolTable* symtab,
- Sink* output, bool ignore_json_unknown) {
- return upb_json_parser_create(
- env, method, symtab, output, ignore_json_unknown);
-}
-inline BytesSink* Parser::input() {
- return upb_json_parser_input(this);
-}
-
-inline const Handlers* ParserMethod::dest_handlers() const {
- return upb_json_parsermethod_desthandlers(this);
-}
-inline const BytesHandler* ParserMethod::input_handler() const {
- return upb_json_parsermethod_inputhandler(this);
-}
-/* static */
-inline reffed_ptr<const ParserMethod> ParserMethod::New(
- const MessageDef* md) {
- const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m);
- return reffed_ptr<const ParserMethod>(m, &m);
-}
+class upb::json::CodeCache {
+ public:
+ CodeCache() : ptr_(upb_json_codecache_new(), upb_json_codecache_free) {}
-} /* namespace json */
-} /* namespace upb */
+ /* Returns a DecoderMethod that can push data to the given handlers.
+ * If a suitable method already exists, it will be returned from the cache. */
+ ParserMethodPtr Get(MessageDefPtr md) {
+ return upb_json_codecache_get(ptr_.get(), md.ptr());
+ }
-#endif
+ private:
+ std::unique_ptr<upb_json_codecache, decltype(&upb_json_codecache_free)> ptr_;
+};
+#endif
#endif /* UPB_JSON_PARSER_H_ */
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index 2fc5027..3444257 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -22,6 +22,7 @@
/* Need to define _XOPEN_SOURCE before any include to make strptime work. */
#define _XOPEN_SOURCE 700
+#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <math.h>
@@ -60,7 +61,6 @@ static bool is_string_wrapper_object(upb_json_parser *p);
static bool does_string_wrapper_start(upb_json_parser *p);
static bool does_string_wrapper_end(upb_json_parser *p);
-static bool is_fieldmask_object(upb_json_parser *p);
static bool does_fieldmask_start(upb_json_parser *p);
static bool does_fieldmask_end(upb_json_parser *p);
static void start_fieldmask_object(upb_json_parser *p);
@@ -157,14 +157,13 @@ void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
typedef struct {
/* For encoding Any value field in binary format. */
- const upb_handlers *encoder_handlers;
- upb_pb_encoder *encoder;
+ upb_handlercache *encoder_handlercache;
upb_stringsink stringsink;
/* For decoding Any value field in json format. */
- upb_json_parsermethod *parser_method;
- upb_json_parser* parser;
+ upb_json_codecache *parser_codecache;
upb_sink sink;
+ upb_json_parser *parser;
/* Mark the range of uninterpreted values in json input before type url. */
const char *before_type_url_start;
@@ -183,7 +182,7 @@ typedef struct {
const upb_fielddef *f;
/* The table mapping json name to fielddef for this message. */
- upb_strtable *name_table;
+ const upb_strtable *name_table;
/* We are in a repeated-field context, ready to emit mapentries as
* submessages. This flag alters the start-of-object (open-brace) behavior to
@@ -216,7 +215,7 @@ typedef struct {
} upb_jsonparser_frame;
struct upb_json_parser {
- upb_env *env;
+ upb_arena *arena;
const upb_json_parsermethod *method;
upb_bytessink input_;
@@ -225,7 +224,7 @@ struct upb_json_parser {
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
- upb_status status;
+ upb_status *status;
/* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
@@ -262,64 +261,68 @@ struct upb_json_parser {
struct tm tm;
};
-struct upb_json_parsermethod {
- upb_refcounted base;
+struct upb_json_codecache {
+ upb_arena *arena;
+ upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */
+};
+struct upb_json_parsermethod {
+ const upb_json_codecache *cache;
upb_byteshandler input_handler_;
- /* Mainly for the purposes of refcounting, so all the fielddefs we point
- * to stay alive. */
- const upb_msgdef *msg;
-
- /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
- upb_inttable name_tables;
+ /* Maps json_name -> fielddef */
+ upb_strtable name_table;
};
#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-static void json_parser_any_frame_reset(upb_jsonparser_any_frame *frame) {
- frame->encoder_handlers = NULL;
- frame->encoder = NULL;
- frame->parser_method = NULL;
+static upb_jsonparser_any_frame *json_parser_any_frame_new(
+ upb_json_parser *p) {
+ upb_jsonparser_any_frame *frame;
+
+ frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
+
+ frame->encoder_handlercache = upb_pb_encoder_newcache();
+ frame->parser_codecache = upb_json_codecache_new();
frame->parser = NULL;
frame->before_type_url_start = NULL;
frame->before_type_url_end = NULL;
frame->after_type_url_start = NULL;
+
+ upb_stringsink_init(&frame->stringsink);
+
+ return frame;
}
static void json_parser_any_frame_set_payload_type(
upb_json_parser *p,
upb_jsonparser_any_frame *frame,
const upb_msgdef *payload_type) {
+ const upb_handlers *h;
+ const upb_json_parsermethod *parser_method;
+ upb_pb_encoder *encoder;
+
/* Initialize encoder. */
- frame->encoder_handlers =
- upb_pb_encoder_newhandlers(payload_type, &frame->encoder_handlers);
- upb_stringsink_init(&frame->stringsink);
- frame->encoder =
- upb_pb_encoder_create(
- p->env, frame->encoder_handlers,
- &frame->stringsink.sink);
+ h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
+ encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
/* Initialize parser. */
- frame->parser_method =
- upb_json_parsermethod_new(payload_type, &frame->parser_method);
- upb_sink_reset(&frame->sink, frame->encoder_handlers, frame->encoder);
+ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
+ upb_sink_reset(&frame->sink, h, encoder);
frame->parser =
- upb_json_parser_create(p->env, frame->parser_method, p->symtab,
- &frame->sink, p->ignore_json_unknown);
+ upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
+ p->status, p->ignore_json_unknown);
}
static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
- upb_handlers_unref(frame->encoder_handlers,
- &frame->encoder_handlers);
- upb_json_parsermethod_unref(frame->parser_method,
- &frame->parser_method);
+ upb_handlercache_free(frame->encoder_handlercache);
+ upb_json_codecache_free(frame->parser_codecache);
upb_stringsink_uninit(&frame->stringsink);
}
static bool json_parser_any_frame_has_type_url(
upb_jsonparser_any_frame *frame) {
- return frame->encoder != NULL;
+ return frame->parser != NULL;
}
static bool json_parser_any_frame_has_value_before_type_url(
@@ -341,7 +344,7 @@ static bool json_parser_any_frame_has_value(
static void json_parser_any_frame_set_before_type_url_end(
upb_jsonparser_any_frame *frame,
const char *ptr) {
- if (frame->encoder == NULL) {
+ if (frame->parser == NULL) {
frame->before_type_url_end = ptr;
}
}
@@ -373,8 +376,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) {
static bool check_stack(upb_json_parser *p) {
if ((p->top + 1) == p->limit) {
- upb_status_seterrmsg(&p->status, "Nesting too deep");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Nesting too deep");
return false;
}
@@ -383,9 +385,15 @@ static bool check_stack(upb_json_parser *p) {
static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
upb_value v;
- bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
+ const upb_json_codecache *cache = p->method->cache;
+ bool ok;
+ const upb_json_parsermethod *method;
+
+ ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
UPB_ASSERT(ok);
- frame->name_table = upb_value_getptr(v);
+ method = upb_value_getconstptr(v);
+
+ frame->name_table = &method->name_table;
}
/* There are GCC/Clang built-ins for overflow checking which we could start
@@ -463,10 +471,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
char output[3];
if (limit - ptr < 4) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -483,17 +490,16 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
output[2] = val & 0xff;
- upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
+ upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
}
return true;
otherchar:
if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
nonbase64(ptr[3]) ) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Non-base64 characters in bytes field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
} if (ptr[2] == '=') {
uint32_t val;
@@ -509,7 +515,7 @@ otherchar:
UPB_ASSERT(!(val & 0x80000000));
output = val >> 16;
- upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
return true;
} else {
uint32_t val;
@@ -526,16 +532,15 @@ otherchar:
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
- upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
+ upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
return true;
}
badpadding:
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Incorrect base64 padding for field: %s (%.*s)",
upb_fielddef_name(p->top->f),
4, ptr);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -579,10 +584,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
new_size = saturating_multiply(new_size, 2);
}
- mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+ mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
if (!mem) {
- upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
}
@@ -605,8 +609,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
}
if (!checked_add(p->accumulated_len, len, &need)) {
- upb_status_seterrmsg(&p->status, "Integer overflow.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
}
@@ -684,8 +687,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
switch (p->multipart_state) {
case MULTIPART_INACTIVE:
upb_status_seterrmsg(
- &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
return false;
case MULTIPART_ACCUMULATE:
@@ -696,7 +698,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
case MULTIPART_PUSHEAGERLY: {
const upb_bufhandle *handle = can_alias ? p->handle : NULL;
- upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
+ upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
break;
}
}
@@ -942,7 +944,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (val > INT32_MAX || val < INT32_MIN) {
return false;
} else {
- upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -953,7 +955,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (val > UINT32_MAX || errno == ERANGE) {
return false;
} else {
- upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putuint32(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -964,7 +966,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
if (errno == ERANGE || end != bufend) {
break;
} else {
- upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -975,7 +977,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
} else if (errno == ERANGE) {
return false;
} else {
- upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
return true;
}
}
@@ -1006,7 +1008,7 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
if (modf(val, &dummy) != 0 || val > max || val < min) { \
return false; \
} else { \
- upb_sink_put ## smalltype(&p->top->sink, parser_getsel(p), \
+ upb_sink_put ## smalltype(p->top->sink, parser_getsel(p), \
(ctype)val); \
return true; \
} \
@@ -1020,13 +1022,13 @@ static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
#undef CASE
case UPB_TYPE_DOUBLE:
- upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
return true;
case UPB_TYPE_FLOAT:
if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
return false;
} else {
- upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
+ upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
return true;
}
default:
@@ -1050,8 +1052,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) {
multipart_end(p);
return true;
} else {
- upb_status_seterrf(&p->status, "error parsing number: %s", buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing number: %s", buf);
multipart_end(p);
return false;
}
@@ -1065,14 +1066,13 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
}
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
- ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+ ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
UPB_ASSERT(ok);
return true;
@@ -1221,7 +1221,7 @@ static bool start_stringval(upb_json_parser *p) {
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
@@ -1252,10 +1252,9 @@ static bool start_stringval(upb_json_parser *p) {
multipart_startaccum(p);
return true;
} else {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"String specified for bool or submessage field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
}
@@ -1271,11 +1270,11 @@ static bool end_any_stringval(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&inner->sink, sel, buf, len, NULL);
+ upb_sink_putstring(inner->sink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&inner->sink, sel);
+ upb_sink_endstr(inner->sink, sel);
multipart_end(p);
@@ -1288,18 +1287,16 @@ static bool end_any_stringval(upb_json_parser *p) {
payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
if (payload_type == NULL) {
upb_status_seterrf(
- &p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
return false;
}
json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
+
return true;
} else {
upb_status_seterrf(
- &p->status, "Invalid type url: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ p->status, "Invalid type url: %.*s\n", (int)len, buf);
return false;
}
}
@@ -1332,15 +1329,14 @@ static bool end_stringval_nontop(upb_json_parser *p) {
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
+ upb_sink_endstr(p->top->sink, sel);
p->top--;
break;
}
case UPB_TYPE_ENUM: {
/* Resolve enum symbolic name to integer value. */
- const upb_enumdef *enumdef =
- (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
+ const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
size_t len;
const char *buf = accumulate_getptr(p, &len);
@@ -1350,10 +1346,9 @@ static bool end_stringval_nontop(upb_json_parser *p) {
if (ok) {
upb_selector_t sel = parser_getsel(p);
- upb_sink_putint32(&p->top->sink, sel, int_val);
+ upb_sink_putint32(p->top->sink, sel, int_val);
} else {
- upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
}
break;
@@ -1370,8 +1365,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
default:
UPB_ASSERT(false);
- upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
ok = false;
break;
}
@@ -1461,25 +1455,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
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",
+ 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: "
+ 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: "
+ upb_status_seterrf(p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1488,9 +1479,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
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",
+ upb_status_seterrf(p->status, "error parsing duration: %s",
nanos_buf);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1505,7 +1495,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
- upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Set nanos */
@@ -1513,10 +1503,10 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
- upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
end_member(p);
- /* Continue previous environment */
+ /* Continue previous arena */
multipart_startaccum(p);
return true;
@@ -1545,15 +1535,13 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) {
timestamp_buf[UPB_TIMESTAMP_BASE_SIZE + 3] = 0;
#if defined __MINGW32__ || defined __MINGW64__
- upb_status_seterrf(
- &p->status, "error parsing timestamp: mingw doesn't support strptime");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status,
+ "error parsing timestamp: mingw doesn't support strptime");
return false;
#else
/* Parse seconds */
if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) {
- upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing timestamp: %s", buf);
return false;
}
#endif
@@ -1587,9 +1575,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
buf = accumulate_getptr(p, &len);
if (len > 10) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"error parsing timestamp: at most 9-digit fraction.");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1599,9 +1586,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len + 1) {
- upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s",
+ upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
nanos_buf);
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1615,7 +1601,7 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
capture_begin(p, nanos_membername);
capture_end(p, nanos_membername + 5);
end_membername(p);
- upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
+ upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
@@ -1643,8 +1629,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
if (buf[0] != 'Z') {
if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
- upb_status_seterrf(&p->status, "error parsing timestamp offset");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "error parsing timestamp offset");
return false;
}
@@ -1660,10 +1645,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
/* Check timestamp boundary */
if (seconds < -62135596800) {
- upb_status_seterrf(&p->status, "error parsing timestamp: "
+ upb_status_seterrf(p->status, "error parsing timestamp: "
"minimum acceptable value is "
"0001-01-01T00:00:00Z");
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -1675,7 +1659,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
capture_begin(p, seconds_membername);
capture_end(p, seconds_membername + 7);
end_membername(p);
- upb_sink_putint64(&p->top->sink, parser_getsel(p), seconds);
+ upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
end_member(p);
/* Continue previous environment */
@@ -1689,9 +1673,7 @@ static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
}
static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
- if (!capture_end(p, ptr)) {
- return false;
- }
+ return capture_end(p, ptr);
}
static bool start_fieldmask_path(upb_json_parser *p) {
@@ -1704,7 +1686,7 @@ static bool start_fieldmask_path(upb_json_parser *p) {
* handler frames, and string events occur in a sub-frame. */
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
inner->name_table = NULL;
@@ -1726,10 +1708,10 @@ static bool lower_camel_push(
for (;ptr < limit; ptr++) {
if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
char lower = tolower(*ptr);
- upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL);
- upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
} else {
- upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL);
+ upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
}
first = false;
}
@@ -1746,7 +1728,7 @@ static bool end_fieldmask_path(upb_json_parser *p) {
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&p->top->sink, sel);
+ upb_sink_endstr(p->top->sink, sel);
p->top--;
multipart_end(p);
@@ -1773,8 +1755,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
- upb_status_seterrmsg(&p->status, "mapentry message has no key");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "mapentry message has no key");
return false;
}
switch (upb_fielddef_type(p->top->f)) {
@@ -1797,9 +1778,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return false;
}
} else {
- upb_status_seterrmsg(&p->status,
+ upb_status_seterrmsg(p->status,
"Map bool key not 'true' or 'false'");
- upb_env_reporterror(p->env, &p->status);
return false;
}
multipart_end(p);
@@ -1808,17 +1788,16 @@ static bool parse_mapentry_key(upb_json_parser *p) {
case UPB_TYPE_BYTES: {
upb_sink subsink;
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, len, &subsink);
+ upb_sink_startstr(p->top->sink, sel, len, &subsink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&subsink, sel, buf, len, NULL);
+ upb_sink_putstring(subsink, sel, buf, len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&subsink, sel);
+ upb_sink_endstr(subsink, sel);
multipart_end(p);
break;
}
default:
- upb_status_seterrmsg(&p->status, "Invalid field type for map key");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Invalid field type for map key");
return false;
}
@@ -1851,7 +1830,7 @@ static bool handle_mapentry(upb_json_parser *p) {
inner = p->top + 1;
p->top->f = mapfield;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+ upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
inner->m = mapentrymsg;
inner->name_table = NULL;
inner->mapfield = mapfield;
@@ -1868,7 +1847,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top = inner;
/* send STARTMSG in submsg frame. */
- upb_sink_startmsg(&p->top->sink);
+ upb_sink_startmsg(p->top->sink);
parse_mapentry_key(p);
@@ -1877,8 +1856,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
p->top->mapfield = mapfield;
if (p->top->f == NULL) {
- upb_status_seterrmsg(&p->status, "mapentry message has no value");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "mapentry message has no value");
return false;
}
@@ -1913,8 +1891,7 @@ static bool end_membername(upb_json_parser *p) {
multipart_end(p);
return true;
} else {
- upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
}
@@ -1940,21 +1917,20 @@ static bool end_any_membername(upb_json_parser *p) {
static void end_member(upb_json_parser *p) {
/* If we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
- upb_status s = UPB_STATUS_INIT;
upb_selector_t sel;
bool ok;
const upb_fielddef *mapfield;
UPB_ASSERT(p->top > p->stack);
/* send ENDMSG on submsg. */
- upb_sink_endmsg(&p->top->sink, &s);
+ upb_sink_endmsg(p->top->sink, p->status);
mapfield = p->top->mapfield;
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--;
ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT(ok);
- upb_sink_endsubmsg(&p->top->sink, sel);
+ upb_sink_endsubmsg(p->top->sink, sel);
}
p->top->f = NULL;
@@ -1998,7 +1974,7 @@ static bool start_subobject(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+ upb_sink_startseq(p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->name_table = NULL;
inner->mapfield = p->top->f;
@@ -2022,7 +1998,7 @@ static bool start_subobject(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
- upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
+ upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
set_name_table(p, inner);
inner->f = NULL;
@@ -2033,9 +2009,7 @@ static bool start_subobject(upb_json_parser *p) {
if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
p->top->is_any = true;
- p->top->any_frame =
- upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
- json_parser_any_frame_reset(p->top->any_frame);
+ p->top->any_frame = json_parser_any_frame_new(p);
} else {
p->top->is_any = false;
p->top->any_frame = NULL;
@@ -2043,10 +2017,9 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Object specified for non-message/group field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
}
@@ -2084,14 +2057,14 @@ static void end_subobject(upb_json_parser *p) {
upb_selector_t sel;
p->top--;
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(&p->top->sink, sel);
+ upb_sink_endseq(p->top->sink, sel);
} else {
upb_selector_t sel;
bool is_unknown = p->top->m == NULL;
p->top--;
if (!is_unknown) {
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
- upb_sink_endsubmsg(&p->top->sink, sel);
+ upb_sink_endsubmsg(p->top->sink, sel);
}
}
}
@@ -2154,10 +2127,9 @@ static bool start_array(upb_json_parser *p) {
}
if (!upb_fielddef_isseq(p->top->f)) {
- upb_status_seterrf(&p->status,
+ upb_status_seterrf(p->status,
"Array specified for non-repeated field: %s",
upb_fielddef_name(p->top->f));
- upb_env_reporterror(p->env, &p->status);
return false;
}
@@ -2165,7 +2137,7 @@ static bool start_array(upb_json_parser *p) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
- upb_sink_startseq(&p->top->sink, sel, &inner->sink);
+ upb_sink_startseq(p->top->sink, sel, &inner->sink);
inner->m = p->top->m;
inner->name_table = NULL;
inner->f = p->top->f;
@@ -2191,7 +2163,7 @@ static void end_array(upb_json_parser *p) {
}
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
- upb_sink_endseq(&p->top->sink, sel);
+ upb_sink_endseq(p->top->sink, sel);
if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
end_listvalue_object(p);
@@ -2210,18 +2182,13 @@ static void end_array(upb_json_parser *p) {
static void start_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
- upb_sink_startmsg(&p->top->sink);
+ upb_sink_startmsg(p->top->sink);
}
}
static void end_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
- upb_status status;
- upb_status_clear(&status);
- upb_sink_endmsg(&p->top->sink, &status);
- if (!upb_ok(&status)) {
- upb_env_reporterror(p->env, &status);
- }
+ upb_sink_endmsg(p->top->sink, p->status);
}
}
@@ -2240,8 +2207,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
if (json_parser_any_frame_has_value(p->top->any_frame) &&
!json_parser_any_frame_has_type_url(p->top->any_frame)) {
- upb_status_seterrmsg(&p->status, "No valid type url");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "No valid type url");
return false;
}
@@ -2256,8 +2222,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
p->top->any_frame->before_type_url_end -
p->top->any_frame->before_type_url_start);
if (p->top->any_frame->before_type_url_start == NULL) {
- upb_status_seterrmsg(&p->status, "invalid data for well known type.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "invalid data for well known type.");
return false;
}
p->top->any_frame->before_type_url_start++;
@@ -2269,8 +2234,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
(ptr + 1) -
p->top->any_frame->after_type_url_start);
if (p->top->any_frame->after_type_url_start == NULL) {
- upb_status_seterrmsg(&p->status, "Invalid data for well known type.");
- upb_env_reporterror(p->env, &p->status);
+ upb_status_seterrmsg(p->status, "Invalid data for well known type.");
return false;
}
p->top->any_frame->after_type_url_start++;
@@ -2330,12 +2294,12 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
inner = p->top + 1;
sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
- upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
+ upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
- upb_sink_putstring(&inner->sink, sel, p->top->any_frame->stringsink.ptr,
+ upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
p->top->any_frame->stringsink.len, NULL);
sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
- upb_sink_endstr(&inner->sink, sel);
+ upb_sink_endstr(inner->sink, sel);
end_member(p);
@@ -2343,7 +2307,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
/* Deallocate any parse frame. */
json_parser_any_frame_free(p->top->any_frame);
- upb_env_free(p->env, p->top->any_frame);
return true;
}
@@ -2527,10 +2490,6 @@ static bool does_fieldmask_end(upb_json_parser *p) {
return p->top->m != NULL && is_fieldmask(p->top->m);
}
-static bool is_fieldmask_object(upb_json_parser *p) {
- return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
#define CHECK_RETURN_TOP(x) if (!(x)) goto error
@@ -2760,8 +2719,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
%% write exec;
if (p != pe) {
- upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
- upb_env_reporterror(parser->env, &parser->status);
+ upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
} else {
capture_suspend(parser, &p);
}
@@ -2812,110 +2770,78 @@ static void json_parser_reset(upb_json_parser *p) {
p->multipart_state = MULTIPART_INACTIVE;
p->capture = NULL;
p->accumulated = NULL;
- upb_status_clear(&p->status);
-}
-
-static void visit_json_parsermethod(const upb_refcounted *r,
- upb_refcounted_visit *visit,
- void *closure) {
- const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
- visit(r, upb_msgdef_upcast2(method->msg), closure);
}
-static void free_json_parsermethod(upb_refcounted *r) {
- upb_json_parsermethod *method = (upb_json_parsermethod*)r;
+static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
+ const upb_msgdef *md) {
+ upb_msg_field_iter i;
+ upb_alloc *alloc = upb_arena_alloc(c->arena);
- upb_inttable_iter i;
- upb_inttable_begin(&i, &method->name_tables);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_value val = upb_inttable_iter_value(&i);
- upb_strtable *t = upb_value_getptr(val);
- upb_strtable_uninit(t);
- upb_gfree(t);
- }
+ upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
- upb_inttable_uninit(&method->name_tables);
+ m->cache = c;
- upb_gfree(r);
-}
+ upb_byteshandler_init(&m->input_handler_);
+ upb_byteshandler_setstring(&m->input_handler_, parse, m);
+ upb_byteshandler_setendstr(&m->input_handler_, end, m);
-static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
- upb_msg_field_iter i;
- upb_strtable *t;
+ upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
- /* It would be nice to stack-allocate this, but protobufs do not limit the
- * length of fields to any reasonable limit. */
- char *buf = NULL;
- size_t len = 0;
-
- if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
- return;
- }
-
- /* TODO(haberman): handle malloc failure. */
- t = upb_gmalloc(sizeof(*t));
- upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
- upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
+ /* Build name_table */
for(upb_msg_field_begin(&i, md);
!upb_msg_field_done(&i);
upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
+ upb_value v = upb_value_constptr(f);
+ char *buf;
/* Add an entry for the JSON name. */
- size_t field_len = upb_fielddef_getjsonname(f, buf, len);
- if (field_len > len) {
- size_t len2;
- buf = upb_grealloc(buf, 0, field_len);
- len = field_len;
- len2 = upb_fielddef_getjsonname(f, buf, len);
- UPB_ASSERT(len == len2);
- }
- upb_strtable_insert(t, buf, upb_value_constptr(f));
+ size_t len = upb_fielddef_getjsonname(f, NULL, 0);
+ buf = upb_malloc(alloc, len);
+ upb_fielddef_getjsonname(f, buf, len);
+ upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc);
if (strcmp(buf, upb_fielddef_name(f)) != 0) {
/* Since the JSON name is different from the regular field name, add an
* entry for the raw name (compliant proto3 JSON parsers must accept
* both). */
- upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
- }
-
- if (upb_fielddef_issubmsg(f)) {
- add_jsonname_table(m, upb_fielddef_msgsubdef(f));
+ const char *name = upb_fielddef_name(f);
+ upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
}
}
- upb_gfree(buf);
+ return m;
}
/* Public API *****************************************************************/
-upb_json_parser *upb_json_parser_create(upb_env *env,
+upb_json_parser *upb_json_parser_create(upb_arena *arena,
const upb_json_parsermethod *method,
const upb_symtab* symtab,
- upb_sink *output,
+ upb_sink output,
+ upb_status *status,
bool ignore_json_unknown) {
#ifndef NDEBUG
- const size_t size_before = upb_env_bytesallocated(env);
+ const size_t size_before = upb_arena_bytesallocated(arena);
#endif
- upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
+ upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
if (!p) return false;
- p->env = env;
+ p->arena = arena;
p->method = method;
+ p->status = status;
p->limit = p->stack + UPB_JSON_MAX_DEPTH;
p->accumulate_buf = NULL;
p->accumulate_buf_size = 0;
upb_bytessink_reset(&p->input_, &method->input_handler_, p);
json_parser_reset(p);
- upb_sink_reset(&p->top->sink, output->handlers, output->closure);
- p->top->m = upb_handlers_msgdef(output->handlers);
+ p->top->sink = output;
+ p->top->m = upb_handlers_msgdef(output.handlers);
if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
p->top->is_any = true;
- p->top->any_frame =
- upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
- json_parser_any_frame_reset(p->top->any_frame);
+ p->top->any_frame = json_parser_any_frame_new(p);
} else {
p->top->is_any = false;
p->top->any_frame = NULL;
@@ -2926,38 +2852,72 @@ upb_json_parser *upb_json_parser_create(upb_env *env,
p->ignore_json_unknown = ignore_json_unknown;
/* If this fails, uncomment and increase the value in parser.h. */
- /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
- UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
+ /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
+ UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
UPB_JSON_PARSER_SIZE);
return p;
}
-upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
- return &p->input_;
+upb_bytessink upb_json_parser_input(upb_json_parser *p) {
+ return p->input_;
}
-upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
- const void* owner) {
- static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
- free_json_parsermethod};
- upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret));
- upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
+const upb_byteshandler *upb_json_parsermethod_inputhandler(
+ const upb_json_parsermethod *m) {
+ return &m->input_handler_;
+}
- ret->msg = md;
- upb_ref2(md, ret);
+upb_json_codecache *upb_json_codecache_new() {
+ upb_alloc *alloc;
+ upb_json_codecache *c;
- upb_byteshandler_init(&ret->input_handler_);
- upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
- upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
+ c = upb_gmalloc(sizeof(*c));
- upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
+ c->arena = upb_arena_new();
+ alloc = upb_arena_alloc(c->arena);
- add_jsonname_table(ret, md);
+ upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
- return ret;
+ return c;
}
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
- const upb_json_parsermethod *m) {
- return &m->input_handler_;
+void upb_json_codecache_free(upb_json_codecache *c) {
+ upb_arena_free(c->arena);
+ upb_gfree(c);
+}
+
+const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
+ const upb_msgdef *md) {
+ upb_json_parsermethod *m;
+ upb_value v;
+ upb_msg_field_iter i;
+ upb_alloc *alloc = upb_arena_alloc(c->arena);
+
+ if (upb_inttable_lookupptr(&c->methods, md, &v)) {
+ return upb_value_getconstptr(v);
+ }
+
+ m = parsermethod_new(c, md);
+ v = upb_value_constptr(m);
+
+ if (!m) return NULL;
+ if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
+
+ /* Populate parser methods for all submessages, so the name tables will
+ * be available during parsing. */
+ for(upb_msg_field_begin(&i, md);
+ !upb_msg_field_done(&i);
+ upb_msg_field_next(&i)) {
+ upb_fielddef *f = upb_msg_iter_field(&i);
+
+ if (upb_fielddef_issubmsg(f)) {
+ const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
+ const upb_json_parsermethod *sub_method =
+ upb_json_codecache_get(c, subdef);
+
+ if (!sub_method) return NULL;
+ }
+ }
+
+ return m;
}
diff --git a/upb/json/printer.c b/upb/json/printer.c
index f0859a3..26cc020 100644
--- a/upb/json/printer.c
+++ b/upb/json/printer.c
@@ -5,15 +5,16 @@
#include "upb/json/printer.h"
-#include <string.h>
+#include <ctype.h>
#include <stdint.h>
+#include <string.h>
#include <time.h>
struct upb_json_printer {
upb_sink input_;
/* BytesSink closure. */
void *subc_;
- upb_bytessink *output_;
+ upb_bytessink output_;
/* We track the depth so that we know when to emit startstr/endstr on the
* output. */
@@ -48,6 +49,10 @@ void freestrpc(void *ptr) {
upb_gfree(pc);
}
+typedef struct {
+ bool preserve_fieldnames;
+} upb_json_printercache;
+
/* Convert fielddef name to JSON name and return as a string piece. */
strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
bool preserve_fieldnames) {
@@ -594,10 +599,10 @@ static void set_enum_hd(upb_handlers *h,
bool preserve_fieldnames,
upb_handlerattr *attr) {
EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
- hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
+ hd->enumdef = upb_fielddef_enumsubdef(f);
hd->keyname = newstrpc(h, f, preserve_fieldnames);
upb_handlers_addcleanup(h, hd, upb_gfree);
- upb_handlerattr_sethandlerdata(attr, hd);
+ attr->handler_data = hd;
}
/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
@@ -622,7 +627,7 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
UPB_UNUSED(closure);
@@ -686,10 +691,9 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
break;
case UPB_TYPE_ENUM: {
- upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
- upb_handlerattr_uninit(&enum_attr);
break;
}
case UPB_TYPE_MESSAGE:
@@ -697,8 +701,6 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
* as appropriate. */
break;
}
-
- upb_handlerattr_uninit(&empty_attr);
}
static bool putseconds(void *closure, const void *handler_data,
@@ -1016,16 +1018,16 @@ void printer_sethandlers_any(const void *closure, upb_handlers *h) {
const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
/* type_url's json name is "@type" */
- upb_handlerattr type_name_attr = UPB_HANDLERATTR_INITIALIZER;
- upb_handlerattr value_name_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT;
+ upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT;
strpc *type_url_json_name = newstrpc_str(h, "@type");
strpc *value_json_name = newstrpc_str(h, "value");
- upb_handlerattr_sethandlerdata(&type_name_attr, type_url_json_name);
- upb_handlerattr_sethandlerdata(&value_name_attr, value_json_name);
+ type_name_attr.handler_data = type_url_json_name;
+ value_name_attr.handler_data = value_json_name;
/* Set up handlers. */
upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
@@ -1049,7 +1051,7 @@ void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_fielddef* f = upb_msgdef_itof(md, 1);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
@@ -1072,7 +1074,7 @@ void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
const upb_fielddef* nanos_field =
upb_msgdef_itof(md, UPB_DURATION_NANOS);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
@@ -1092,7 +1094,7 @@ void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
const upb_fielddef* nanos_field =
upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
@@ -1106,7 +1108,7 @@ void printer_sethandlers_value(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
upb_msg_field_iter i;
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
@@ -1145,7 +1147,7 @@ void printer_sethandlers_value(const void *closure, upb_handlers *h) {
void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \
const upb_msgdef *md = upb_handlers_msgdef(h); \
const upb_fielddef* f = upb_msgdef_itof(md, 1); \
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; \
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; \
upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); \
upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); \
upb_handlers_set##type(h, f, putmethod, &empty_attr); \
@@ -1168,7 +1170,7 @@ void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_fielddef* f = upb_msgdef_itof(md, 1);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr);
upb_handlers_setendseq(h, f, endseq, &empty_attr);
@@ -1185,7 +1187,7 @@ void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
const upb_fielddef* f = upb_msgdef_itof(md, 1);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr);
upb_handlers_setendseq(h, f, endmap, &empty_attr);
@@ -1201,10 +1203,10 @@ void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
void printer_sethandlers(const void *closure, upb_handlers *h) {
const upb_msgdef *md = upb_handlers_msgdef(h);
bool is_mapentry = upb_msgdef_mapentry(md);
- upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
upb_msg_field_iter i;
- const bool *preserve_fieldnames_ptr = closure;
- const bool preserve_fieldnames = *preserve_fieldnames_ptr;
+ const upb_json_printercache *cache = closure;
+ const bool preserve_fieldnames = cache->preserve_fieldnames;
if (is_mapentry) {
/* mapentry messages are sufficiently different that we handle them
@@ -1271,9 +1273,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
- upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
- upb_handlerattr_sethandlerdata(&name_attr,
- newstrpc(h, f, preserve_fieldnames));
+ upb_handlerattr name_attr = UPB_HANDLERATTR_INIT;
+ name_attr.handler_data = newstrpc(h, f, preserve_fieldnames);
if (upb_fielddef_ismap(f)) {
upb_handlers_setstartseq(h, f, startmap, &name_attr);
@@ -1295,7 +1296,7 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
/* For now, we always emit symbolic names for enums. We may want an
* option later to control this behavior, but we will wait for a real
* need first. */
- upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
if (upb_fielddef_isseq(f)) {
@@ -1304,7 +1305,6 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
}
- upb_handlerattr_uninit(&enum_attr);
break;
}
case UPB_TYPE_STRING:
@@ -1335,11 +1335,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
}
break;
}
-
- upb_handlerattr_uninit(&name_attr);
}
- upb_handlerattr_uninit(&empty_attr);
#undef TYPE
}
@@ -1350,13 +1347,13 @@ static void json_printer_reset(upb_json_printer *p) {
/* Public API *****************************************************************/
-upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
- upb_bytessink *output) {
+upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
+ upb_bytessink output) {
#ifndef NDEBUG
- size_t size_before = upb_env_bytesallocated(e);
+ size_t size_before = upb_arena_bytesallocated(a);
#endif
- upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
+ upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
if (!p) return NULL;
p->output_ = output;
@@ -1366,18 +1363,21 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
p->nanos = 0;
/* If this fails, increase the value in printer.h. */
- UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <=
+ UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
UPB_JSON_PRINTER_SIZE);
return p;
}
-upb_sink *upb_json_printer_input(upb_json_printer *p) {
- return &p->input_;
+upb_sink upb_json_printer_input(upb_json_printer *p) {
+ return p->input_;
}
-const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
- bool preserve_fieldnames,
- const void *owner) {
- return upb_handlers_newfrozen(
- md, owner, printer_sethandlers, &preserve_fieldnames);
+upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) {
+ upb_json_printercache *cache = upb_gmalloc(sizeof(*cache));
+ upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache);
+
+ cache->preserve_fieldnames = preserve_proto_fieldnames;
+ upb_handlercache_addcleanup(ret, cache, upb_gfree);
+
+ return ret;
}
diff --git a/upb/json/printer.h b/upb/json/printer.h
index 80644f1..85b9b12 100644
--- a/upb/json/printer.h
+++ b/upb/json/printer.h
@@ -12,74 +12,61 @@
#ifdef __cplusplus
namespace upb {
namespace json {
-class Printer;
+class PrinterPtr;
} /* namespace json */
} /* namespace upb */
#endif
-UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer)
+/* upb_json_printer ***********************************************************/
+#define UPB_JSON_PRINTER_SIZE 192
-/* upb::json::Printer *********************************************************/
+struct upb_json_printer;
+typedef struct upb_json_printer upb_json_printer;
-#define UPB_JSON_PRINTER_SIZE 192
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Native C API. */
+upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
+ upb_bytessink output);
+upb_sink upb_json_printer_input(upb_json_printer *p);
+const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
+ bool preserve_fieldnames,
+ const void *owner);
+
+/* Lazily builds and caches handlers that will push encoded data to a bytessink.
+ * Any msgdef objects used with this object must outlive it. */
+upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames);
#ifdef __cplusplus
+} /* extern "C" */
/* Prints an incoming stream of data to a BytesSink in JSON format. */
-class upb::json::Printer {
+class upb::json::PrinterPtr {
public:
- static Printer* Create(Environment* env, const upb::Handlers* handlers,
- BytesSink* output);
+ PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {}
- /* The input to the printer. */
- Sink* input();
+ static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers,
+ BytesSink output) {
+ return PrinterPtr(
+ upb_json_printer_create(arena->ptr(), handlers, output.sink()));
+ }
- /* Returns handlers for printing according to the specified schema.
- * If preserve_proto_fieldnames is true, the output JSON will use the
- * original .proto field names (ie. {"my_field":3}) instead of using
- * camelCased names, which is the default: (eg. {"myField":3}). */
- static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md,
- bool preserve_proto_fieldnames);
+ /* The input to the printer. */
+ Sink input() { return upb_json_printer_input(ptr_); }
static const size_t kSize = UPB_JSON_PRINTER_SIZE;
+ static HandlerCache NewCache(bool preserve_proto_fieldnames) {
+ return upb_json_printer_newcache(preserve_proto_fieldnames);
+ }
+
private:
- UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer)
+ upb_json_printer* ptr_;
};
-#endif
-
-UPB_BEGIN_EXTERN_C
-
-/* Native C API. */
-upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
- upb_bytessink *output);
-upb_sink *upb_json_printer_input(upb_json_printer *p);
-const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
- bool preserve_fieldnames,
- const void *owner);
-
-UPB_END_EXTERN_C
-
-#ifdef __cplusplus
-
-namespace upb {
-namespace json {
-inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers,
- BytesSink* output) {
- return upb_json_printer_create(env, handlers, output);
-}
-inline Sink* Printer::input() { return upb_json_printer_input(this); }
-inline reffed_ptr<const Handlers> Printer::NewHandlers(
- const upb::MessageDef *md, bool preserve_proto_fieldnames) {
- const Handlers* h = upb_json_printer_newhandlers(
- md, preserve_proto_fieldnames, &h);
- return reffed_ptr<const Handlers>(h, &h);
-}
-} /* namespace json */
-} /* namespace upb */
-
-#endif
+#endif /* __cplusplus */
#endif /* UPB_JSON_TYPED_PRINTER_H_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback