summaryrefslogtreecommitdiff
path: root/upb/json
diff options
context:
space:
mode:
Diffstat (limited to 'upb/json')
-rw-r--r--upb/json/parser.c562
-rw-r--r--upb/json/parser.h25
-rw-r--r--upb/json/parser.rl490
-rw-r--r--upb/json/printer.c226
-rw-r--r--upb/json/printer.h22
5 files changed, 717 insertions, 608 deletions
diff --git a/upb/json/parser.c b/upb/json/parser.c
index f4f5628..896f18f 100644
--- a/upb/json/parser.c
+++ b/upb/json/parser.c
@@ -38,26 +38,26 @@
typedef struct {
upb_sink sink;
- // The current message in which we're parsing, and the field whose value we're
- // expecting next.
+ /* The current message in which we're parsing, and the field whose value we're
+ * expecting next. */
const upb_msgdef *m;
const upb_fielddef *f;
- // We are in a repeated-field context, ready to emit mapentries as
- // submessages. This flag alters the start-of-object (open-brace) behavior to
- // begin a sequence of mapentry messages rather than a single submessage.
+ /* We are in a repeated-field context, ready to emit mapentries as
+ * submessages. This flag alters the start-of-object (open-brace) behavior to
+ * begin a sequence of mapentry messages rather than a single submessage. */
bool is_map;
- // We are in a map-entry message context. This flag is set when parsing the
- // value field of a single map entry and indicates to all value-field parsers
- // (subobjects, strings, numbers, and bools) that the map-entry submessage
- // should end as soon as the value is parsed.
+ /* We are in a map-entry message context. This flag is set when parsing the
+ * value field of a single map entry and indicates to all value-field parsers
+ * (subobjects, strings, numbers, and bools) that the map-entry submessage
+ * should end as soon as the value is parsed. */
bool is_mapentry;
- // If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
- // message's map field that we're currently parsing. This differs from |f|
- // because |f| is the field in the *current* message (i.e., the map-entry
- // message itself), not the parent's field that leads to this map.
+ /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
+ * message's map field that we're currently parsing. This differs from |f|
+ * because |f| is the field in the *current* message (i.e., the map-entry
+ * message itself), not the parent's field that leads to this map. */
const upb_fielddef *mapfield;
} upb_jsonparser_frame;
@@ -66,41 +66,41 @@ struct upb_json_parser {
upb_byteshandler input_handler_;
upb_bytessink input_;
- // Stack to track the JSON scopes we are in.
+ /* Stack to track the JSON scopes we are in. */
upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
upb_status *status;
- // Ragel's internal parsing stack for the parsing state machine.
+ /* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
int parser_stack[UPB_JSON_MAX_DEPTH];
int parser_top;
- // The handle for the current buffer.
+ /* The handle for the current buffer. */
const upb_bufhandle *handle;
- // Accumulate buffer. See details in parser.rl.
+ /* Accumulate buffer. See details in parser.rl. */
const char *accumulated;
size_t accumulated_len;
char *accumulate_buf;
size_t accumulate_buf_size;
- // Multi-part text data. See details in parser.rl.
+ /* Multi-part text data. See details in parser.rl. */
int multipart_state;
upb_selector_t string_selector;
- // Input capture. See details in parser.rl.
+ /* Input capture. See details in parser.rl. */
const char *capture;
- // Intermediate result of parsing a unicode escape sequence.
+ /* Intermediate result of parsing a unicode escape sequence. */
uint32_t digit;
};
#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-// Used to signal that a capture has been suspended.
+/* Used to signal that a capture has been suspended. */
static char suspend_capture;
static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
@@ -125,8 +125,8 @@ static bool check_stack(upb_json_parser *p) {
return true;
}
-// There are GCC/Clang built-ins for overflow checking which we could start
-// using if there was any performance benefit to it.
+/* There are GCC/Clang built-ins for overflow checking which we could start
+ * using if there was any performance benefit to it. */
static bool checked_add(size_t a, size_t b, size_t *c) {
if (SIZE_MAX - a < b) return false;
@@ -135,7 +135,7 @@ static bool checked_add(size_t a, size_t b, size_t *c) {
}
static size_t saturating_multiply(size_t a, size_t b) {
- // size_t is unsigned, so this is defined behavior even on overflow.
+ /* size_t is unsigned, so this is defined behavior even on overflow. */
size_t ret = a * b;
if (b != 0 && ret / b != a) {
ret = SIZE_MAX;
@@ -146,7 +146,7 @@ static size_t saturating_multiply(size_t a, size_t b) {
/* Base64 decoding ************************************************************/
-// TODO(haberman): make this streaming.
+/* TODO(haberman): make this streaming. */
static const signed char b64table[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -183,19 +183,22 @@ static const signed char b64table[] = {
-1, -1, -1, -1, -1, -1, -1, -1
};
-// Returns the table value sign-extended to 32 bits. Knowing that the upper
-// bits will be 1 for unrecognized characters makes it easier to check for
-// this error condition later (see below).
+/* Returns the table value sign-extended to 32 bits. Knowing that the upper
+ * bits will be 1 for unrecognized characters makes it easier to check for
+ * this error condition later (see below). */
int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-// Returns true if the given character is not a valid base64 character or
-// padding.
+/* Returns true if the given character is not a valid base64 character or
+ * padding. */
bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
size_t len) {
const char *limit = ptr + len;
for (; ptr < limit; ptr += 4) {
+ uint32_t val;
+ char output[3];
+
if (limit - ptr < 4) {
upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
@@ -203,17 +206,16 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
return false;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6 |
- b64lookup(ptr[3]);
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12 |
+ b64lookup(ptr[2]) << 6 |
+ b64lookup(ptr[3]);
- // Test the upper bit; returns true if any of the characters returned -1.
+ /* Test the upper bit; returns true if any of the characters returned -1. */
if (val & 0x80000000) {
goto otherchar;
}
- char output[3];
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
output[2] = val & 0xff;
@@ -229,29 +231,34 @@ otherchar:
upb_fielddef_name(p->top->f));
return false;
} if (ptr[2] == '=') {
- // Last group contains only two input bytes, one output byte.
+ uint32_t val;
+ char output;
+
+ /* Last group contains only two input bytes, one output byte. */
if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
goto badpadding;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12;
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12;
assert(!(val & 0x80000000));
- char output = val >> 16;
+ output = val >> 16;
upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
return true;
} else {
- // Last group contains only three input bytes, two output bytes.
+ uint32_t val;
+ char output[2];
+
+ /* Last group contains only three input bytes, two output bytes. */
if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
goto badpadding;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6;
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12 |
+ b64lookup(ptr[2]) << 6;
- char output[2];
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
@@ -269,23 +276,23 @@ badpadding:
/* Accumulate buffer **********************************************************/
-// Functionality for accumulating a buffer.
-//
-// Some parts of the parser need an entire value as a contiguous string. For
-// example, to look up a member name in a hash table, or to turn a string into
-// a number, the relevant library routines need the input string to be in
-// contiguous memory, even if the value spanned two or more buffers in the
-// input. These routines handle that.
-//
-// In the common case we can just point to the input buffer to get this
-// contiguous string and avoid any actual copy. So we optimistically begin
-// this way. But there are a few cases where we must instead copy into a
-// separate buffer:
-//
-// 1. The string was not contiguous in the input (it spanned buffers).
-//
-// 2. The string included escape sequences that need to be interpreted to get
-// the true value in a contiguous buffer.
+/* Functionality for accumulating a buffer.
+ *
+ * Some parts of the parser need an entire value as a contiguous string. For
+ * example, to look up a member name in a hash table, or to turn a string into
+ * a number, the relevant library routines need the input string to be in
+ * contiguous memory, even if the value spanned two or more buffers in the
+ * input. These routines handle that.
+ *
+ * In the common case we can just point to the input buffer to get this
+ * contiguous string and avoid any actual copy. So we optimistically begin
+ * this way. But there are a few cases where we must instead copy into a
+ * separate buffer:
+ *
+ * 1. The string was not contiguous in the input (it spanned buffers).
+ *
+ * 2. The string included escape sequences that need to be interpreted to get
+ * the true value in a contiguous buffer. */
static void assert_accumulate_empty(upb_json_parser *p) {
UPB_UNUSED(p);
@@ -298,15 +305,16 @@ static void accumulate_clear(upb_json_parser *p) {
p->accumulated_len = 0;
}
-// Used internally by accumulate_append().
+/* Used internally by accumulate_append(). */
static bool accumulate_realloc(upb_json_parser *p, size_t need) {
+ void *mem;
size_t old_size = p->accumulate_buf_size;
size_t new_size = UPB_MAX(old_size, 128);
while (new_size < need) {
new_size = saturating_multiply(new_size, 2);
}
- void *mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+ mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
if (!mem) {
upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
@@ -317,18 +325,19 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
return true;
}
-// Logically appends the given data to the append buffer.
-// If "can_alias" is true, we will try to avoid actually copying, but the buffer
-// must be valid until the next accumulate_append() call (if any).
+/* Logically appends the given data to the append buffer.
+ * If "can_alias" is true, we will try to avoid actually copying, but the buffer
+ * must be valid until the next accumulate_append() call (if any). */
static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
bool can_alias) {
+ size_t need;
+
if (!p->accumulated && can_alias) {
p->accumulated = buf;
p->accumulated_len = len;
return true;
}
- size_t need;
if (!checked_add(p->accumulated_len, len, &need)) {
upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
@@ -348,9 +357,9 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
return true;
}
-// Returns a pointer to the data accumulated since the last accumulate_clear()
-// call, and writes the length to *len. This with point either to the input
-// buffer or a temporary accumulate buffer.
+/* Returns a pointer to the data accumulated since the last accumulate_clear()
+ * call, and writes the length to *len. This with point either to the input
+ * buffer or a temporary accumulate buffer. */
static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
assert(p->accumulated);
*len = p->accumulated_len;
@@ -360,42 +369,42 @@ static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
/* Mult-part text data ********************************************************/
-// When we have text data in the input, it can often come in multiple segments.
-// For example, there may be some raw string data followed by an escape
-// sequence. The two segments are processed with different logic. Also buffer
-// seams in the input can cause multiple segments.
-//
-// As we see segments, there are two main cases for how we want to process them:
-//
-// 1. we want to push the captured input directly to string handlers.
-//
-// 2. we need to accumulate all the parts into a contiguous buffer for further
-// processing (field name lookup, string->number conversion, etc).
-
-// This is the set of states for p->multipart_state.
+/* When we have text data in the input, it can often come in multiple segments.
+ * For example, there may be some raw string data followed by an escape
+ * sequence. The two segments are processed with different logic. Also buffer
+ * seams in the input can cause multiple segments.
+ *
+ * As we see segments, there are two main cases for how we want to process them:
+ *
+ * 1. we want to push the captured input directly to string handlers.
+ *
+ * 2. we need to accumulate all the parts into a contiguous buffer for further
+ * processing (field name lookup, string->number conversion, etc). */
+
+/* This is the set of states for p->multipart_state. */
enum {
- // We are not currently processing multipart data.
+ /* We are not currently processing multipart data. */
MULTIPART_INACTIVE = 0,
- // We are processing multipart data by accumulating it into a contiguous
- // buffer.
+ /* We are processing multipart data by accumulating it into a contiguous
+ * buffer. */
MULTIPART_ACCUMULATE = 1,
- // We are processing multipart data by pushing each part directly to the
- // current string handlers.
+ /* We are processing multipart data by pushing each part directly to the
+ * current string handlers. */
MULTIPART_PUSHEAGERLY = 2
};
-// Start a multi-part text value where we accumulate the data for processing at
-// the end.
+/* Start a multi-part text value where we accumulate the data for processing at
+ * the end. */
static void multipart_startaccum(upb_json_parser *p) {
assert_accumulate_empty(p);
assert(p->multipart_state == MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_ACCUMULATE;
}
-// Start a multi-part text value where we immediately push text data to a string
-// value with the given selector.
+/* Start a multi-part text value where we immediately push text data to a string
+ * value with the given selector. */
static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
assert_accumulate_empty(p);
assert(p->multipart_state == MULTIPART_INACTIVE);
@@ -427,8 +436,8 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
return true;
}
-// Note: this invalidates the accumulate buffer! Call only after reading its
-// contents.
+/* Note: this invalidates the accumulate buffer! Call only after reading its
+ * contents. */
static void multipart_end(upb_json_parser *p) {
assert(p->multipart_state != MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_INACTIVE;
@@ -438,9 +447,9 @@ static void multipart_end(upb_json_parser *p) {
/* Input capture **************************************************************/
-// Functionality for capturing a region of the input as text. Gracefully
-// handles the case where a buffer seam occurs in the middle of the captured
-// region.
+/* Functionality for capturing a region of the input as text. Gracefully
+ * handles the case where a buffer seam occurs in the middle of the captured
+ * region. */
static void capture_begin(upb_json_parser *p, const char *ptr) {
assert(p->multipart_state != MULTIPART_INACTIVE);
@@ -458,24 +467,24 @@ static bool capture_end(upb_json_parser *p, const char *ptr) {
}
}
-// This is called at the end of each input buffer (ie. when we have hit a
-// buffer seam). If we are in the middle of capturing the input, this
-// processes the unprocessed capture region.
+/* This is called at the end of each input buffer (ie. when we have hit a
+ * buffer seam). If we are in the middle of capturing the input, this
+ * processes the unprocessed capture region. */
static void capture_suspend(upb_json_parser *p, const char **ptr) {
if (!p->capture) return;
if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
- // We use this as a signal that we were in the middle of capturing, and
- // that capturing should resume at the beginning of the next buffer.
- //
- // We can't use *ptr here, because we have no guarantee that this pointer
- // will be valid when we resume (if the underlying memory is freed, then
- // using the pointer at all, even to compare to NULL, is likely undefined
- // behavior).
+ /* We use this as a signal that we were in the middle of capturing, and
+ * that capturing should resume at the beginning of the next buffer.
+ *
+ * We can't use *ptr here, because we have no guarantee that this pointer
+ * will be valid when we resume (if the underlying memory is freed, then
+ * using the pointer at all, even to compare to NULL, is likely undefined
+ * behavior). */
p->capture = &suspend_capture;
} else {
- // Need to back up the pointer to the beginning of the capture, since
- // we were not able to actually preserve it.
+ /* Need to back up the pointer to the beginning of the capture, since
+ * we were not able to actually preserve it. */
*ptr = p->capture;
}
}
@@ -490,8 +499,8 @@ static void capture_resume(upb_json_parser *p, const char *ptr) {
/* Callbacks from the parser **************************************************/
-// These are the functions called directly from the parser itself.
-// We define these in the same order as their declarations in the parser.
+/* These are the functions called directly from the parser itself.
+ * We define these in the same order as their declarations in the parser. */
static char escape_char(char in) {
switch (in) {
@@ -536,8 +545,8 @@ static void hexdigit(upb_json_parser *p, const char *ptr) {
static bool end_hex(upb_json_parser *p) {
uint32_t codepoint = p->digit;
- // emit the codepoint as UTF-8.
- char utf8[3]; // support \u0000 -- \uFFFF -- need only three bytes.
+ /* emit the codepoint as UTF-8. */
+ char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
int length = 0;
if (codepoint <= 0x7F) {
utf8[0] = codepoint;
@@ -555,8 +564,8 @@ static bool end_hex(upb_json_parser *p) {
utf8[0] = (codepoint & 0x0F) | 0xE0;
length = 3;
}
- // TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
- // we have to wait for the next escape to get the full code point).
+ /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
+ * we have to wait for the next escape to get the full code point). */
return multipart_text(p, utf8, length, false);
}
@@ -585,17 +594,29 @@ static bool end_number(upb_json_parser *p, const char *ptr) {
}
static bool parse_number(upb_json_parser *p) {
- // strtol() and friends unfortunately do not support specifying the length of
- // the input string, so we need to force a copy into a NULL-terminated buffer.
+ size_t len;
+ const char *buf;
+ const char *myend;
+ char *end;
+
+ /* strtol() and friends unfortunately do not support specifying the length of
+ * the input string, so we need to force a copy into a NULL-terminated buffer. */
if (!multipart_text(p, "\0", 1, false)) {
return false;
}
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
- const char *myend = buf + len - 1; // One for NULL.
-
- char *end;
+ buf = accumulate_getptr(p, &len);
+ myend = buf + len - 1; /* One for NULL. */
+
+ /* XXX: We are using strtol to parse integers, but this is wrong as even
+ * integers can be represented as 1e6 (for example), which strtol can't
+ * handle correctly.
+ *
+ * XXX: Also, we can't handle large integers properly because strto[u]ll
+ * isn't in C89.
+ *
+ * XXX: Also, we don't properly check floats for overflow, since strtof
+ * isn't in C89. */
switch (upb_fielddef_type(p->top->f)) {
case UPB_TYPE_ENUM:
case UPB_TYPE_INT32: {
@@ -607,7 +628,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_INT64: {
- long long val = strtoll(p->accumulated, &end, 0);
+ long long val = strtol(p->accumulated, &end, 0);
if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
goto err;
else
@@ -623,7 +644,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_UINT64: {
- unsigned long long val = strtoull(p->accumulated, &end, 0);
+ unsigned long long val = strtoul(p->accumulated, &end, 0);
if (val > UINT64_MAX || errno == ERANGE || end != myend)
goto err;
else
@@ -639,7 +660,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_FLOAT: {
- float val = strtof(p->accumulated, &end);
+ float val = strtod(p->accumulated, &end);
if (errno == ERANGE || end != myend)
goto err;
else
@@ -661,6 +682,8 @@ err:
}
static bool parser_putbool(upb_json_parser *p, bool val) {
+ bool ok;
+
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
@@ -668,7 +691,7 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
return false;
}
- bool ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+ ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
UPB_ASSERT_VAR(ok, ok);
return true;
@@ -678,12 +701,15 @@ static bool start_stringval(upb_json_parser *p) {
assert(p->top->f);
if (upb_fielddef_isstring(p->top->f)) {
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
if (!check_stack(p)) return false;
- // Start a new parser frame: parser frames correspond one-to-one with
- // handler frames, and string events occur in a sub-frame.
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+ /* Start a new parser frame: parser frames correspond one-to-one with
+ * 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);
inner->m = p->top->m;
inner->f = p->top->f;
@@ -692,11 +718,11 @@ static bool start_stringval(upb_json_parser *p) {
p->top = inner;
if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
- // For STRING fields we push data directly to the handlers as it is
- // parsed. We don't do this yet for BYTES fields, because our base64
- // decoder is not streaming.
- //
- // TODO(haberman): make base64 decoding streaming also.
+ /* For STRING fields we push data directly to the handlers as it is
+ * parsed. We don't do this yet for BYTES fields, because our base64
+ * decoder is not streaming.
+ *
+ * TODO(haberman): make base64 decoding streaming also. */
multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
return true;
} else {
@@ -704,11 +730,11 @@ static bool start_stringval(upb_json_parser *p) {
return true;
}
} else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
- // No need to push a frame -- symbolic enum names in quotes remain in the
- // current parser frame.
- //
- // Enum string values must accumulate so we can look up the value in a table
- // once it is complete.
+ /* No need to push a frame -- symbolic enum names in quotes remain in the
+ * current parser frame.
+ *
+ * Enum string values must accumulate so we can look up the value in a table
+ * once it is complete. */
multipart_startaccum(p);
return true;
} else {
@@ -728,7 +754,7 @@ static bool end_stringval(upb_json_parser *p) {
p->accumulated, p->accumulated_len)) {
return false;
}
- // Fall through.
+ /* Fall through. */
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
@@ -738,7 +764,7 @@ static bool end_stringval(upb_json_parser *p) {
}
case UPB_TYPE_ENUM: {
- // Resolve enum symbolic name to integer value.
+ /* Resolve enum symbolic name to integer value. */
const upb_enumdef *enumdef =
(const upb_enumdef*)upb_fielddef_subdef(p->top->f);
@@ -775,18 +801,18 @@ static void start_member(upb_json_parser *p) {
multipart_startaccum(p);
}
-// Helper: invoked during parse_mapentry() to emit the mapentry message's key
-// field based on the current contents of the accumulate buffer.
+/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
+ * field based on the current contents of the accumulate buffer. */
static bool parse_mapentry_key(upb_json_parser *p) {
size_t len;
const char *buf = accumulate_getptr(p, &len);
- // Emit the key field. We do a bit of ad-hoc parsing here because the
- // parser state machine has already decided that this is a string field
- // name, and we are reinterpreting it as some arbitrary key type. In
- // particular, integer and bool keys are quoted, so we need to parse the
- // quoted string contents here.
+ /* Emit the key field. We do a bit of ad-hoc parsing here because the
+ * parser state machine has already decided that this is a string field
+ * name, and we are reinterpreting it as some arbitrary key type. In
+ * particular, integer and bool keys are quoted, so we need to parse the
+ * quoted string contents here. */
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
@@ -798,7 +824,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
case UPB_TYPE_INT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_UINT64:
- // Invoke end_number. The accum buffer has the number's text already.
+ /* Invoke end_number. The accum buffer has the number's text already. */
if (!parse_number(p)) {
return false;
}
@@ -839,47 +865,52 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return true;
}
-// Helper: emit one map entry (as a submessage in the map field sequence). This
-// is invoked from end_membername(), at the end of the map entry's key string,
-// with the map key in the accumulate buffer. It parses the key from that
-// buffer, emits the handler calls to start the mapentry submessage (setting up
-// its subframe in the process), and sets up state in the subframe so that the
-// value parser (invoked next) will emit the mapentry's value field and then
-// end the mapentry message.
+/* Helper: emit one map entry (as a submessage in the map field sequence). This
+ * is invoked from end_membername(), at the end of the map entry's key string,
+ * with the map key in the accumulate buffer. It parses the key from that
+ * buffer, emits the handler calls to start the mapentry submessage (setting up
+ * its subframe in the process), and sets up state in the subframe so that the
+ * value parser (invoked next) will emit the mapentry's value field and then
+ * end the mapentry message. */
static bool handle_mapentry(upb_json_parser *p) {
- // Map entry: p->top->sink is the seq frame, so we need to start a frame
- // for the mapentry itself, and then set |f| in that frame so that the map
- // value field is parsed, and also set a flag to end the frame after the
- // map-entry value is parsed.
+ const upb_fielddef *mapfield;
+ const upb_msgdef *mapentrymsg;
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Map entry: p->top->sink is the seq frame, so we need to start a frame
+ * for the mapentry itself, and then set |f| in that frame so that the map
+ * value field is parsed, and also set a flag to end the frame after the
+ * map-entry value is parsed. */
if (!check_stack(p)) return false;
- const upb_fielddef *mapfield = p->top->mapfield;
- const upb_msgdef *mapentrymsg = upb_fielddef_msgsubdef(mapfield);
+ mapfield = p->top->mapfield;
+ mapentrymsg = upb_fielddef_msgsubdef(mapfield);
- upb_jsonparser_frame *inner = p->top + 1;
+ inner = p->top + 1;
p->top->f = mapfield;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = mapentrymsg;
inner->mapfield = mapfield;
inner->is_map = false;
- // Don't set this to true *yet* -- we reuse parsing handlers below to push
- // the key field value to the sink, and these handlers will pop the frame
- // if they see is_mapentry (when invoked by the parser state machine, they
- // would have just seen the map-entry value, not key).
+ /* Don't set this to true *yet* -- we reuse parsing handlers below to push
+ * the key field value to the sink, and these handlers will pop the frame
+ * if they see is_mapentry (when invoked by the parser state machine, they
+ * would have just seen the map-entry value, not key). */
inner->is_mapentry = false;
p->top = inner;
- // send STARTMSG in submsg frame.
+ /* send STARTMSG in submsg frame. */
upb_sink_startmsg(&p->top->sink);
parse_mapentry_key(p);
- // Set up the value field to receive the map-entry value.
+ /* Set up the value field to receive the map-entry value. */
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
- p->top->is_mapentry = true; // set up to pop frame after value is parsed.
+ 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");
@@ -900,7 +931,8 @@ static bool end_membername(upb_json_parser *p) {
const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
if (!f) {
- // TODO(haberman): Ignore unknown fields if requested/configured to do so.
+ /* TODO(haberman): Ignore unknown fields if requested/configured to do
+ * so. */
upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
@@ -913,19 +945,21 @@ static bool end_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 we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
- assert(p->top > p->stack);
- // send ENDMSG on submsg.
upb_status s = UPB_STATUS_INIT;
+ upb_selector_t sel;
+ bool ok;
+ const upb_fielddef *mapfield;
+
+ assert(p->top > p->stack);
+ /* send ENDMSG on submsg. */
upb_sink_endmsg(&p->top->sink, &s);
- const upb_fielddef* mapfield = p->top->mapfield;
+ mapfield = p->top->mapfield;
- // send ENDSUBMSG in repeated-field-of-mapentries frame.
+ /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--;
- upb_selector_t sel;
- bool ok = upb_handlers_getselector(mapfield,
- UPB_HANDLER_ENDSUBMSG, &sel);
+ ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT_VAR(ok, ok);
upb_sink_endsubmsg(&p->top->sink, sel);
}
@@ -937,12 +971,15 @@ static bool start_subobject(upb_json_parser *p) {
assert(p->top->f);
if (upb_fielddef_ismap(p->top->f)) {
- // Beginning of a map. Start a new parser frame in a repeated-field
- // context.
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Beginning of a map. Start a new parser frame in a repeated-field
+ * context. */
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+ inner = p->top + 1;
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->mapfield = p->top->f;
@@ -953,13 +990,16 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else if (upb_fielddef_issubmsg(p->top->f)) {
- // Beginning of a subobject. Start a new parser frame in the submsg
- // context.
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Beginning of a subobject. Start a new parser frame in the submsg
+ * context. */
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
+ inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->f = NULL;
@@ -978,17 +1018,22 @@ static bool start_subobject(upb_json_parser *p) {
static void end_subobject(upb_json_parser *p) {
if (p->top->is_map) {
+ upb_selector_t sel;
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
upb_sink_endseq(&p->top->sink, sel);
} else {
+ upb_selector_t sel;
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
upb_sink_endsubmsg(&p->top->sink, sel);
}
}
static bool start_array(upb_json_parser *p) {
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
assert(p->top->f);
if (!upb_fielddef_isseq(p->top->f)) {
@@ -1000,8 +1045,8 @@ static bool start_array(upb_json_parser *p) {
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+ inner = p->top + 1;
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
@@ -1013,10 +1058,12 @@ static bool start_array(upb_json_parser *p) {
}
static void end_array(upb_json_parser *p) {
+ upb_selector_t sel;
+
assert(p->top > p->stack);
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
upb_sink_endseq(&p->top->sink, sel);
}
@@ -1039,27 +1086,27 @@ static void end_object(upb_json_parser *p) {
/* The actual parser **********************************************************/
-// What follows is the Ragel parser itself. The language is specified in Ragel
-// and the actions call our C functions above.
-//
-// Ragel has an extensive set of functionality, and we use only a small part of
-// it. There are many action types but we only use a few:
-//
-// ">" -- transition into a machine
-// "%" -- transition out of a machine
-// "@" -- transition into a final state of a machine.
-//
-// "@" transitions are tricky because a machine can transition into a final
-// state repeatedly. But in some cases we know this can't happen, for example
-// a string which is delimited by a final '"' can only transition into its
-// final state once, when the closing '"' is seen.
+/* What follows is the Ragel parser itself. The language is specified in Ragel
+ * and the actions call our C functions above.
+ *
+ * Ragel has an extensive set of functionality, and we use only a small part of
+ * it. There are many action types but we only use a few:
+ *
+ * ">" -- transition into a machine
+ * "%" -- transition out of a machine
+ * "@" -- transition into a final state of a machine.
+ *
+ * "@" transitions are tricky because a machine can transition into a final
+ * state repeatedly. But in some cases we know this can't happen, for example
+ * a string which is delimited by a final '"' can only transition into its
+ * final state once, when the closing '"' is seen. */
-#line 1151 "upb/json/parser.rl"
+#line 1198 "upb/json/parser.rl"
-#line 1063 "upb/json/parser.c"
+#line 1110 "upb/json/parser.c"
static const char _json_actions[] = {
0, 1, 0, 1, 2, 1, 3, 1,
5, 1, 6, 1, 7, 1, 8, 1,
@@ -1208,16 +1255,13 @@ static const int json_en_value_machine = 27;
static const int json_en_main = 1;
-#line 1154 "upb/json/parser.rl"
+#line 1201 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
- UPB_UNUSED(hd);
- UPB_UNUSED(handle);
upb_json_parser *parser = closure;
- parser->handle = handle;
- // Variables used by Ragel's generated code.
+ /* Variables used by Ragel's generated code. */
int cs = parser->current_state;
int *stack = parser->parser_stack;
int top = parser->parser_top;
@@ -1225,10 +1269,15 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const char *p = buf;
const char *pe = buf + size;
+ parser->handle = handle;
+
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
capture_resume(parser, buf);
-#line 1232 "upb/json/parser.c"
+#line 1281 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@@ -1303,118 +1352,118 @@ _match:
switch ( *_acts++ )
{
case 0:
-#line 1066 "upb/json/parser.rl"
+#line 1113 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 1:
-#line 1067 "upb/json/parser.rl"
+#line 1114 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
break;
case 2:
-#line 1071 "upb/json/parser.rl"
+#line 1118 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 3:
-#line 1072 "upb/json/parser.rl"
+#line 1119 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 4:
-#line 1078 "upb/json/parser.rl"
+#line 1125 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 5:
-#line 1079 "upb/json/parser.rl"
+#line 1126 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 6:
-#line 1080 "upb/json/parser.rl"
+#line 1127 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 7:
-#line 1086 "upb/json/parser.rl"
+#line 1133 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 8:
-#line 1092 "upb/json/parser.rl"
+#line 1139 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 9:
-#line 1095 "upb/json/parser.rl"
+#line 1142 "upb/json/parser.rl"
{ {stack[top++] = cs; cs = 19; goto _again;} }
break;
case 10:
-#line 1097 "upb/json/parser.rl"
+#line 1144 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
break;
case 11:
-#line 1102 "upb/json/parser.rl"
+#line 1149 "upb/json/parser.rl"
{ start_member(parser); }
break;
case 12:
-#line 1103 "upb/json/parser.rl"
+#line 1150 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 13:
-#line 1106 "upb/json/parser.rl"
+#line 1153 "upb/json/parser.rl"
{ end_member(parser); }
break;
case 14:
-#line 1112 "upb/json/parser.rl"
+#line 1159 "upb/json/parser.rl"
{ start_object(parser); }
break;
case 15:
-#line 1115 "upb/json/parser.rl"
+#line 1162 "upb/json/parser.rl"
{ end_object(parser); }
break;
case 16:
-#line 1121 "upb/json/parser.rl"
+#line 1168 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 17:
-#line 1125 "upb/json/parser.rl"
+#line 1172 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 18:
-#line 1130 "upb/json/parser.rl"
+#line 1177 "upb/json/parser.rl"
{ start_number(parser, p); }
break;
case 19:
-#line 1131 "upb/json/parser.rl"
+#line 1178 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 20:
-#line 1133 "upb/json/parser.rl"
+#line 1180 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 21:
-#line 1134 "upb/json/parser.rl"
+#line 1181 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 22:
-#line 1136 "upb/json/parser.rl"
+#line 1183 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
break;
case 23:
-#line 1138 "upb/json/parser.rl"
+#line 1185 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
break;
case 24:
-#line 1140 "upb/json/parser.rl"
+#line 1187 "upb/json/parser.rl"
{ /* null value */ }
break;
case 25:
-#line 1142 "upb/json/parser.rl"
+#line 1189 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject(parser)); }
break;
case 26:
-#line 1143 "upb/json/parser.rl"
+#line 1190 "upb/json/parser.rl"
{ end_subobject(parser); }
break;
case 27:
-#line 1148 "upb/json/parser.rl"
+#line 1195 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
-#line 1418 "upb/json/parser.c"
+#line 1467 "upb/json/parser.c"
}
}
@@ -1427,7 +1476,7 @@ _again:
_out: {}
}
-#line 1173 "upb/json/parser.rl"
+#line 1222 "upb/json/parser.rl"
if (p != pe) {
upb_status_seterrf(parser->status, "Parse error at %s\n", p);
@@ -1436,7 +1485,7 @@ _again:
}
error:
- // Save parsing state back to parser.
+ /* Save parsing state back to parser. */
parser->current_state = cs;
parser->parser_top = top;
@@ -1447,7 +1496,7 @@ bool end(void *closure, const void *hd) {
UPB_UNUSED(closure);
UPB_UNUSED(hd);
- // Prevent compile warning on unused static constants.
+ /* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
@@ -1457,22 +1506,23 @@ bool end(void *closure, const void *hd) {
}
static void json_parser_reset(upb_json_parser *p) {
+ int cs;
+ int top;
+
p->top = p->stack;
p->top->f = NULL;
p->top->is_map = false;
p->top->is_mapentry = false;
- int cs;
- int top;
- // Emit Ragel initialization of the parser.
+ /* Emit Ragel initialization of the parser. */
-#line 1470 "upb/json/parser.c"
+#line 1520 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
-#line 1211 "upb/json/parser.rl"
+#line 1261 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);
@@ -1504,8 +1554,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
upb_sink_reset(&p->top->sink, output->handlers, output->closure);
p->top->m = upb_handlers_msgdef(output->handlers);
- // If this fails, uncomment and increase the value in parser.h.
- // fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before);
+ /* If this fails, uncomment and increase the value in parser.h.
+ * fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
return p;
}
diff --git a/upb/json/parser.h b/upb/json/parser.h
index b932adf..2facb45 100644
--- a/upb/json/parser.h
+++ b/upb/json/parser.h
@@ -18,23 +18,24 @@
namespace upb {
namespace json {
class Parser;
-} // namespace json
-} // namespace upb
+} /* namespace json */
+} /* namespace upb */
#endif
-UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser);
+UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
/* 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.
-// But if the parser library is upgraded without recompiling the application,
-// it may be an underestimate.
+/* Preallocation hint: parser won't allocate more bytes than this when first
+ * constructed. This hint may be an overestimate for some build configurations.
+ * But if the parser library is upgraded without recompiling the application,
+ * it may be an underestimate. */
#define UPB_JSON_PARSER_SIZE 3568
#ifdef __cplusplus
-// Parses an incoming BytesStream, pushing the results to the destination sink.
+/* Parses an incoming BytesStream, pushing the results to the destination
+ * sink. */
class upb::json::Parser {
public:
static Parser* Create(Environment* env, Sink* output);
@@ -42,7 +43,7 @@ class upb::json::Parser {
BytesSink* input();
private:
- UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser);
+ UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser)
};
#endif
@@ -64,10 +65,10 @@ inline Parser* Parser::Create(Environment* env, Sink* output) {
inline BytesSink* Parser::input() {
return upb_json_parser_input(this);
}
-} // namespace json
-} // namespace upb
+} /* namespace json */
+} /* namespace upb */
#endif
-#endif // UPB_JSON_PARSER_H_
+#endif /* UPB_JSON_PARSER_H_ */
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index 81d1514..deccb48 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -36,26 +36,26 @@
typedef struct {
upb_sink sink;
- // The current message in which we're parsing, and the field whose value we're
- // expecting next.
+ /* The current message in which we're parsing, and the field whose value we're
+ * expecting next. */
const upb_msgdef *m;
const upb_fielddef *f;
- // We are in a repeated-field context, ready to emit mapentries as
- // submessages. This flag alters the start-of-object (open-brace) behavior to
- // begin a sequence of mapentry messages rather than a single submessage.
+ /* We are in a repeated-field context, ready to emit mapentries as
+ * submessages. This flag alters the start-of-object (open-brace) behavior to
+ * begin a sequence of mapentry messages rather than a single submessage. */
bool is_map;
- // We are in a map-entry message context. This flag is set when parsing the
- // value field of a single map entry and indicates to all value-field parsers
- // (subobjects, strings, numbers, and bools) that the map-entry submessage
- // should end as soon as the value is parsed.
+ /* We are in a map-entry message context. This flag is set when parsing the
+ * value field of a single map entry and indicates to all value-field parsers
+ * (subobjects, strings, numbers, and bools) that the map-entry submessage
+ * should end as soon as the value is parsed. */
bool is_mapentry;
- // If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
- // message's map field that we're currently parsing. This differs from |f|
- // because |f| is the field in the *current* message (i.e., the map-entry
- // message itself), not the parent's field that leads to this map.
+ /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
+ * message's map field that we're currently parsing. This differs from |f|
+ * because |f| is the field in the *current* message (i.e., the map-entry
+ * message itself), not the parent's field that leads to this map. */
const upb_fielddef *mapfield;
} upb_jsonparser_frame;
@@ -64,41 +64,41 @@ struct upb_json_parser {
upb_byteshandler input_handler_;
upb_bytessink input_;
- // Stack to track the JSON scopes we are in.
+ /* Stack to track the JSON scopes we are in. */
upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
upb_status *status;
- // Ragel's internal parsing stack for the parsing state machine.
+ /* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
int parser_stack[UPB_JSON_MAX_DEPTH];
int parser_top;
- // The handle for the current buffer.
+ /* The handle for the current buffer. */
const upb_bufhandle *handle;
- // Accumulate buffer. See details in parser.rl.
+ /* Accumulate buffer. See details in parser.rl. */
const char *accumulated;
size_t accumulated_len;
char *accumulate_buf;
size_t accumulate_buf_size;
- // Multi-part text data. See details in parser.rl.
+ /* Multi-part text data. See details in parser.rl. */
int multipart_state;
upb_selector_t string_selector;
- // Input capture. See details in parser.rl.
+ /* Input capture. See details in parser.rl. */
const char *capture;
- // Intermediate result of parsing a unicode escape sequence.
+ /* Intermediate result of parsing a unicode escape sequence. */
uint32_t digit;
};
#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-// Used to signal that a capture has been suspended.
+/* Used to signal that a capture has been suspended. */
static char suspend_capture;
static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
@@ -123,8 +123,8 @@ static bool check_stack(upb_json_parser *p) {
return true;
}
-// There are GCC/Clang built-ins for overflow checking which we could start
-// using if there was any performance benefit to it.
+/* There are GCC/Clang built-ins for overflow checking which we could start
+ * using if there was any performance benefit to it. */
static bool checked_add(size_t a, size_t b, size_t *c) {
if (SIZE_MAX - a < b) return false;
@@ -133,7 +133,7 @@ static bool checked_add(size_t a, size_t b, size_t *c) {
}
static size_t saturating_multiply(size_t a, size_t b) {
- // size_t is unsigned, so this is defined behavior even on overflow.
+ /* size_t is unsigned, so this is defined behavior even on overflow. */
size_t ret = a * b;
if (b != 0 && ret / b != a) {
ret = SIZE_MAX;
@@ -144,7 +144,7 @@ static size_t saturating_multiply(size_t a, size_t b) {
/* Base64 decoding ************************************************************/
-// TODO(haberman): make this streaming.
+/* TODO(haberman): make this streaming. */
static const signed char b64table[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -181,19 +181,22 @@ static const signed char b64table[] = {
-1, -1, -1, -1, -1, -1, -1, -1
};
-// Returns the table value sign-extended to 32 bits. Knowing that the upper
-// bits will be 1 for unrecognized characters makes it easier to check for
-// this error condition later (see below).
+/* Returns the table value sign-extended to 32 bits. Knowing that the upper
+ * bits will be 1 for unrecognized characters makes it easier to check for
+ * this error condition later (see below). */
int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-// Returns true if the given character is not a valid base64 character or
-// padding.
+/* Returns true if the given character is not a valid base64 character or
+ * padding. */
bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
size_t len) {
const char *limit = ptr + len;
for (; ptr < limit; ptr += 4) {
+ uint32_t val;
+ char output[3];
+
if (limit - ptr < 4) {
upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
@@ -201,17 +204,16 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
return false;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6 |
- b64lookup(ptr[3]);
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12 |
+ b64lookup(ptr[2]) << 6 |
+ b64lookup(ptr[3]);
- // Test the upper bit; returns true if any of the characters returned -1.
+ /* Test the upper bit; returns true if any of the characters returned -1. */
if (val & 0x80000000) {
goto otherchar;
}
- char output[3];
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
output[2] = val & 0xff;
@@ -227,29 +229,34 @@ otherchar:
upb_fielddef_name(p->top->f));
return false;
} if (ptr[2] == '=') {
- // Last group contains only two input bytes, one output byte.
+ uint32_t val;
+ char output;
+
+ /* Last group contains only two input bytes, one output byte. */
if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
goto badpadding;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12;
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12;
assert(!(val & 0x80000000));
- char output = val >> 16;
+ output = val >> 16;
upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
return true;
} else {
- // Last group contains only three input bytes, two output bytes.
+ uint32_t val;
+ char output[2];
+
+ /* Last group contains only three input bytes, two output bytes. */
if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
goto badpadding;
}
- uint32_t val = b64lookup(ptr[0]) << 18 |
- b64lookup(ptr[1]) << 12 |
- b64lookup(ptr[2]) << 6;
+ val = b64lookup(ptr[0]) << 18 |
+ b64lookup(ptr[1]) << 12 |
+ b64lookup(ptr[2]) << 6;
- char output[2];
output[0] = val >> 16;
output[1] = (val >> 8) & 0xff;
upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
@@ -267,23 +274,23 @@ badpadding:
/* Accumulate buffer **********************************************************/
-// Functionality for accumulating a buffer.
-//
-// Some parts of the parser need an entire value as a contiguous string. For
-// example, to look up a member name in a hash table, or to turn a string into
-// a number, the relevant library routines need the input string to be in
-// contiguous memory, even if the value spanned two or more buffers in the
-// input. These routines handle that.
-//
-// In the common case we can just point to the input buffer to get this
-// contiguous string and avoid any actual copy. So we optimistically begin
-// this way. But there are a few cases where we must instead copy into a
-// separate buffer:
-//
-// 1. The string was not contiguous in the input (it spanned buffers).
-//
-// 2. The string included escape sequences that need to be interpreted to get
-// the true value in a contiguous buffer.
+/* Functionality for accumulating a buffer.
+ *
+ * Some parts of the parser need an entire value as a contiguous string. For
+ * example, to look up a member name in a hash table, or to turn a string into
+ * a number, the relevant library routines need the input string to be in
+ * contiguous memory, even if the value spanned two or more buffers in the
+ * input. These routines handle that.
+ *
+ * In the common case we can just point to the input buffer to get this
+ * contiguous string and avoid any actual copy. So we optimistically begin
+ * this way. But there are a few cases where we must instead copy into a
+ * separate buffer:
+ *
+ * 1. The string was not contiguous in the input (it spanned buffers).
+ *
+ * 2. The string included escape sequences that need to be interpreted to get
+ * the true value in a contiguous buffer. */
static void assert_accumulate_empty(upb_json_parser *p) {
UPB_UNUSED(p);
@@ -296,15 +303,16 @@ static void accumulate_clear(upb_json_parser *p) {
p->accumulated_len = 0;
}
-// Used internally by accumulate_append().
+/* Used internally by accumulate_append(). */
static bool accumulate_realloc(upb_json_parser *p, size_t need) {
+ void *mem;
size_t old_size = p->accumulate_buf_size;
size_t new_size = UPB_MAX(old_size, 128);
while (new_size < need) {
new_size = saturating_multiply(new_size, 2);
}
- void *mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
+ mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
if (!mem) {
upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
@@ -315,18 +323,19 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
return true;
}
-// Logically appends the given data to the append buffer.
-// If "can_alias" is true, we will try to avoid actually copying, but the buffer
-// must be valid until the next accumulate_append() call (if any).
+/* Logically appends the given data to the append buffer.
+ * If "can_alias" is true, we will try to avoid actually copying, but the buffer
+ * must be valid until the next accumulate_append() call (if any). */
static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
bool can_alias) {
+ size_t need;
+
if (!p->accumulated && can_alias) {
p->accumulated = buf;
p->accumulated_len = len;
return true;
}
- size_t need;
if (!checked_add(p->accumulated_len, len, &need)) {
upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
@@ -346,9 +355,9 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
return true;
}
-// Returns a pointer to the data accumulated since the last accumulate_clear()
-// call, and writes the length to *len. This with point either to the input
-// buffer or a temporary accumulate buffer.
+/* Returns a pointer to the data accumulated since the last accumulate_clear()
+ * call, and writes the length to *len. This with point either to the input
+ * buffer or a temporary accumulate buffer. */
static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
assert(p->accumulated);
*len = p->accumulated_len;
@@ -358,42 +367,42 @@ static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
/* Mult-part text data ********************************************************/
-// When we have text data in the input, it can often come in multiple segments.
-// For example, there may be some raw string data followed by an escape
-// sequence. The two segments are processed with different logic. Also buffer
-// seams in the input can cause multiple segments.
-//
-// As we see segments, there are two main cases for how we want to process them:
-//
-// 1. we want to push the captured input directly to string handlers.
-//
-// 2. we need to accumulate all the parts into a contiguous buffer for further
-// processing (field name lookup, string->number conversion, etc).
-
-// This is the set of states for p->multipart_state.
+/* When we have text data in the input, it can often come in multiple segments.
+ * For example, there may be some raw string data followed by an escape
+ * sequence. The two segments are processed with different logic. Also buffer
+ * seams in the input can cause multiple segments.
+ *
+ * As we see segments, there are two main cases for how we want to process them:
+ *
+ * 1. we want to push the captured input directly to string handlers.
+ *
+ * 2. we need to accumulate all the parts into a contiguous buffer for further
+ * processing (field name lookup, string->number conversion, etc). */
+
+/* This is the set of states for p->multipart_state. */
enum {
- // We are not currently processing multipart data.
+ /* We are not currently processing multipart data. */
MULTIPART_INACTIVE = 0,
- // We are processing multipart data by accumulating it into a contiguous
- // buffer.
+ /* We are processing multipart data by accumulating it into a contiguous
+ * buffer. */
MULTIPART_ACCUMULATE = 1,
- // We are processing multipart data by pushing each part directly to the
- // current string handlers.
+ /* We are processing multipart data by pushing each part directly to the
+ * current string handlers. */
MULTIPART_PUSHEAGERLY = 2
};
-// Start a multi-part text value where we accumulate the data for processing at
-// the end.
+/* Start a multi-part text value where we accumulate the data for processing at
+ * the end. */
static void multipart_startaccum(upb_json_parser *p) {
assert_accumulate_empty(p);
assert(p->multipart_state == MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_ACCUMULATE;
}
-// Start a multi-part text value where we immediately push text data to a string
-// value with the given selector.
+/* Start a multi-part text value where we immediately push text data to a string
+ * value with the given selector. */
static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
assert_accumulate_empty(p);
assert(p->multipart_state == MULTIPART_INACTIVE);
@@ -425,8 +434,8 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
return true;
}
-// Note: this invalidates the accumulate buffer! Call only after reading its
-// contents.
+/* Note: this invalidates the accumulate buffer! Call only after reading its
+ * contents. */
static void multipart_end(upb_json_parser *p) {
assert(p->multipart_state != MULTIPART_INACTIVE);
p->multipart_state = MULTIPART_INACTIVE;
@@ -436,9 +445,9 @@ static void multipart_end(upb_json_parser *p) {
/* Input capture **************************************************************/
-// Functionality for capturing a region of the input as text. Gracefully
-// handles the case where a buffer seam occurs in the middle of the captured
-// region.
+/* Functionality for capturing a region of the input as text. Gracefully
+ * handles the case where a buffer seam occurs in the middle of the captured
+ * region. */
static void capture_begin(upb_json_parser *p, const char *ptr) {
assert(p->multipart_state != MULTIPART_INACTIVE);
@@ -456,24 +465,24 @@ static bool capture_end(upb_json_parser *p, const char *ptr) {
}
}
-// This is called at the end of each input buffer (ie. when we have hit a
-// buffer seam). If we are in the middle of capturing the input, this
-// processes the unprocessed capture region.
+/* This is called at the end of each input buffer (ie. when we have hit a
+ * buffer seam). If we are in the middle of capturing the input, this
+ * processes the unprocessed capture region. */
static void capture_suspend(upb_json_parser *p, const char **ptr) {
if (!p->capture) return;
if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
- // We use this as a signal that we were in the middle of capturing, and
- // that capturing should resume at the beginning of the next buffer.
- //
- // We can't use *ptr here, because we have no guarantee that this pointer
- // will be valid when we resume (if the underlying memory is freed, then
- // using the pointer at all, even to compare to NULL, is likely undefined
- // behavior).
+ /* We use this as a signal that we were in the middle of capturing, and
+ * that capturing should resume at the beginning of the next buffer.
+ *
+ * We can't use *ptr here, because we have no guarantee that this pointer
+ * will be valid when we resume (if the underlying memory is freed, then
+ * using the pointer at all, even to compare to NULL, is likely undefined
+ * behavior). */
p->capture = &suspend_capture;
} else {
- // Need to back up the pointer to the beginning of the capture, since
- // we were not able to actually preserve it.
+ /* Need to back up the pointer to the beginning of the capture, since
+ * we were not able to actually preserve it. */
*ptr = p->capture;
}
}
@@ -488,8 +497,8 @@ static void capture_resume(upb_json_parser *p, const char *ptr) {
/* Callbacks from the parser **************************************************/
-// These are the functions called directly from the parser itself.
-// We define these in the same order as their declarations in the parser.
+/* These are the functions called directly from the parser itself.
+ * We define these in the same order as their declarations in the parser. */
static char escape_char(char in) {
switch (in) {
@@ -534,8 +543,8 @@ static void hexdigit(upb_json_parser *p, const char *ptr) {
static bool end_hex(upb_json_parser *p) {
uint32_t codepoint = p->digit;
- // emit the codepoint as UTF-8.
- char utf8[3]; // support \u0000 -- \uFFFF -- need only three bytes.
+ /* emit the codepoint as UTF-8. */
+ char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
int length = 0;
if (codepoint <= 0x7F) {
utf8[0] = codepoint;
@@ -553,8 +562,8 @@ static bool end_hex(upb_json_parser *p) {
utf8[0] = (codepoint & 0x0F) | 0xE0;
length = 3;
}
- // TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
- // we have to wait for the next escape to get the full code point).
+ /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
+ * we have to wait for the next escape to get the full code point). */
return multipart_text(p, utf8, length, false);
}
@@ -583,17 +592,29 @@ static bool end_number(upb_json_parser *p, const char *ptr) {
}
static bool parse_number(upb_json_parser *p) {
- // strtol() and friends unfortunately do not support specifying the length of
- // the input string, so we need to force a copy into a NULL-terminated buffer.
+ size_t len;
+ const char *buf;
+ const char *myend;
+ char *end;
+
+ /* strtol() and friends unfortunately do not support specifying the length of
+ * the input string, so we need to force a copy into a NULL-terminated buffer. */
if (!multipart_text(p, "\0", 1, false)) {
return false;
}
- size_t len;
- const char *buf = accumulate_getptr(p, &len);
- const char *myend = buf + len - 1; // One for NULL.
-
- char *end;
+ buf = accumulate_getptr(p, &len);
+ myend = buf + len - 1; /* One for NULL. */
+
+ /* XXX: We are using strtol to parse integers, but this is wrong as even
+ * integers can be represented as 1e6 (for example), which strtol can't
+ * handle correctly.
+ *
+ * XXX: Also, we can't handle large integers properly because strto[u]ll
+ * isn't in C89.
+ *
+ * XXX: Also, we don't properly check floats for overflow, since strtof
+ * isn't in C89. */
switch (upb_fielddef_type(p->top->f)) {
case UPB_TYPE_ENUM:
case UPB_TYPE_INT32: {
@@ -605,7 +626,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_INT64: {
- long long val = strtoll(p->accumulated, &end, 0);
+ long long val = strtol(p->accumulated, &end, 0);
if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
goto err;
else
@@ -621,7 +642,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_UINT64: {
- unsigned long long val = strtoull(p->accumulated, &end, 0);
+ unsigned long long val = strtoul(p->accumulated, &end, 0);
if (val > UINT64_MAX || errno == ERANGE || end != myend)
goto err;
else
@@ -637,7 +658,7 @@ static bool parse_number(upb_json_parser *p) {
break;
}
case UPB_TYPE_FLOAT: {
- float val = strtof(p->accumulated, &end);
+ float val = strtod(p->accumulated, &end);
if (errno == ERANGE || end != myend)
goto err;
else
@@ -659,6 +680,8 @@ err:
}
static bool parser_putbool(upb_json_parser *p, bool val) {
+ bool ok;
+
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
@@ -666,7 +689,7 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
return false;
}
- bool ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
+ ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
UPB_ASSERT_VAR(ok, ok);
return true;
@@ -676,12 +699,15 @@ static bool start_stringval(upb_json_parser *p) {
assert(p->top->f);
if (upb_fielddef_isstring(p->top->f)) {
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
if (!check_stack(p)) return false;
- // Start a new parser frame: parser frames correspond one-to-one with
- // handler frames, and string events occur in a sub-frame.
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
+ /* Start a new parser frame: parser frames correspond one-to-one with
+ * 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);
inner->m = p->top->m;
inner->f = p->top->f;
@@ -690,11 +716,11 @@ static bool start_stringval(upb_json_parser *p) {
p->top = inner;
if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
- // For STRING fields we push data directly to the handlers as it is
- // parsed. We don't do this yet for BYTES fields, because our base64
- // decoder is not streaming.
- //
- // TODO(haberman): make base64 decoding streaming also.
+ /* For STRING fields we push data directly to the handlers as it is
+ * parsed. We don't do this yet for BYTES fields, because our base64
+ * decoder is not streaming.
+ *
+ * TODO(haberman): make base64 decoding streaming also. */
multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
return true;
} else {
@@ -702,11 +728,11 @@ static bool start_stringval(upb_json_parser *p) {
return true;
}
} else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
- // No need to push a frame -- symbolic enum names in quotes remain in the
- // current parser frame.
- //
- // Enum string values must accumulate so we can look up the value in a table
- // once it is complete.
+ /* No need to push a frame -- symbolic enum names in quotes remain in the
+ * current parser frame.
+ *
+ * Enum string values must accumulate so we can look up the value in a table
+ * once it is complete. */
multipart_startaccum(p);
return true;
} else {
@@ -726,7 +752,7 @@ static bool end_stringval(upb_json_parser *p) {
p->accumulated, p->accumulated_len)) {
return false;
}
- // Fall through.
+ /* Fall through. */
case UPB_TYPE_STRING: {
upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
@@ -736,7 +762,7 @@ static bool end_stringval(upb_json_parser *p) {
}
case UPB_TYPE_ENUM: {
- // Resolve enum symbolic name to integer value.
+ /* Resolve enum symbolic name to integer value. */
const upb_enumdef *enumdef =
(const upb_enumdef*)upb_fielddef_subdef(p->top->f);
@@ -773,18 +799,18 @@ static void start_member(upb_json_parser *p) {
multipart_startaccum(p);
}
-// Helper: invoked during parse_mapentry() to emit the mapentry message's key
-// field based on the current contents of the accumulate buffer.
+/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
+ * field based on the current contents of the accumulate buffer. */
static bool parse_mapentry_key(upb_json_parser *p) {
size_t len;
const char *buf = accumulate_getptr(p, &len);
- // Emit the key field. We do a bit of ad-hoc parsing here because the
- // parser state machine has already decided that this is a string field
- // name, and we are reinterpreting it as some arbitrary key type. In
- // particular, integer and bool keys are quoted, so we need to parse the
- // quoted string contents here.
+ /* Emit the key field. We do a bit of ad-hoc parsing here because the
+ * parser state machine has already decided that this is a string field
+ * name, and we are reinterpreting it as some arbitrary key type. In
+ * particular, integer and bool keys are quoted, so we need to parse the
+ * quoted string contents here. */
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
@@ -796,7 +822,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
case UPB_TYPE_INT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_UINT64:
- // Invoke end_number. The accum buffer has the number's text already.
+ /* Invoke end_number. The accum buffer has the number's text already. */
if (!parse_number(p)) {
return false;
}
@@ -837,47 +863,52 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return true;
}
-// Helper: emit one map entry (as a submessage in the map field sequence). This
-// is invoked from end_membername(), at the end of the map entry's key string,
-// with the map key in the accumulate buffer. It parses the key from that
-// buffer, emits the handler calls to start the mapentry submessage (setting up
-// its subframe in the process), and sets up state in the subframe so that the
-// value parser (invoked next) will emit the mapentry's value field and then
-// end the mapentry message.
+/* Helper: emit one map entry (as a submessage in the map field sequence). This
+ * is invoked from end_membername(), at the end of the map entry's key string,
+ * with the map key in the accumulate buffer. It parses the key from that
+ * buffer, emits the handler calls to start the mapentry submessage (setting up
+ * its subframe in the process), and sets up state in the subframe so that the
+ * value parser (invoked next) will emit the mapentry's value field and then
+ * end the mapentry message. */
static bool handle_mapentry(upb_json_parser *p) {
- // Map entry: p->top->sink is the seq frame, so we need to start a frame
- // for the mapentry itself, and then set |f| in that frame so that the map
- // value field is parsed, and also set a flag to end the frame after the
- // map-entry value is parsed.
+ const upb_fielddef *mapfield;
+ const upb_msgdef *mapentrymsg;
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Map entry: p->top->sink is the seq frame, so we need to start a frame
+ * for the mapentry itself, and then set |f| in that frame so that the map
+ * value field is parsed, and also set a flag to end the frame after the
+ * map-entry value is parsed. */
if (!check_stack(p)) return false;
- const upb_fielddef *mapfield = p->top->mapfield;
- const upb_msgdef *mapentrymsg = upb_fielddef_msgsubdef(mapfield);
+ mapfield = p->top->mapfield;
+ mapentrymsg = upb_fielddef_msgsubdef(mapfield);
- upb_jsonparser_frame *inner = p->top + 1;
+ inner = p->top + 1;
p->top->f = mapfield;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = mapentrymsg;
inner->mapfield = mapfield;
inner->is_map = false;
- // Don't set this to true *yet* -- we reuse parsing handlers below to push
- // the key field value to the sink, and these handlers will pop the frame
- // if they see is_mapentry (when invoked by the parser state machine, they
- // would have just seen the map-entry value, not key).
+ /* Don't set this to true *yet* -- we reuse parsing handlers below to push
+ * the key field value to the sink, and these handlers will pop the frame
+ * if they see is_mapentry (when invoked by the parser state machine, they
+ * would have just seen the map-entry value, not key). */
inner->is_mapentry = false;
p->top = inner;
- // send STARTMSG in submsg frame.
+ /* send STARTMSG in submsg frame. */
upb_sink_startmsg(&p->top->sink);
parse_mapentry_key(p);
- // Set up the value field to receive the map-entry value.
+ /* Set up the value field to receive the map-entry value. */
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
- p->top->is_mapentry = true; // set up to pop frame after value is parsed.
+ 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");
@@ -898,7 +929,8 @@ static bool end_membername(upb_json_parser *p) {
const upb_fielddef *f = upb_msgdef_ntof(p->top->m, buf, len);
if (!f) {
- // TODO(haberman): Ignore unknown fields if requested/configured to do so.
+ /* TODO(haberman): Ignore unknown fields if requested/configured to do
+ * so. */
upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
@@ -911,19 +943,21 @@ static bool end_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 we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
- assert(p->top > p->stack);
- // send ENDMSG on submsg.
upb_status s = UPB_STATUS_INIT;
+ upb_selector_t sel;
+ bool ok;
+ const upb_fielddef *mapfield;
+
+ assert(p->top > p->stack);
+ /* send ENDMSG on submsg. */
upb_sink_endmsg(&p->top->sink, &s);
- const upb_fielddef* mapfield = p->top->mapfield;
+ mapfield = p->top->mapfield;
- // send ENDSUBMSG in repeated-field-of-mapentries frame.
+ /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--;
- upb_selector_t sel;
- bool ok = upb_handlers_getselector(mapfield,
- UPB_HANDLER_ENDSUBMSG, &sel);
+ ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT_VAR(ok, ok);
upb_sink_endsubmsg(&p->top->sink, sel);
}
@@ -935,12 +969,15 @@ static bool start_subobject(upb_json_parser *p) {
assert(p->top->f);
if (upb_fielddef_ismap(p->top->f)) {
- // Beginning of a map. Start a new parser frame in a repeated-field
- // context.
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Beginning of a map. Start a new parser frame in a repeated-field
+ * context. */
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+ inner = p->top + 1;
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->mapfield = p->top->f;
@@ -951,13 +988,16 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else if (upb_fielddef_issubmsg(p->top->f)) {
- // Beginning of a subobject. Start a new parser frame in the submsg
- // context.
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
+ /* Beginning of a subobject. Start a new parser frame in the submsg
+ * context. */
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
+ inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
inner->m = upb_fielddef_msgsubdef(p->top->f);
inner->f = NULL;
@@ -976,17 +1016,22 @@ static bool start_subobject(upb_json_parser *p) {
static void end_subobject(upb_json_parser *p) {
if (p->top->is_map) {
+ upb_selector_t sel;
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
upb_sink_endseq(&p->top->sink, sel);
} else {
+ upb_selector_t sel;
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
upb_sink_endsubmsg(&p->top->sink, sel);
}
}
static bool start_array(upb_json_parser *p) {
+ upb_jsonparser_frame *inner;
+ upb_selector_t sel;
+
assert(p->top->f);
if (!upb_fielddef_isseq(p->top->f)) {
@@ -998,8 +1043,8 @@ static bool start_array(upb_json_parser *p) {
if (!check_stack(p)) return false;
- upb_jsonparser_frame *inner = p->top + 1;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
+ inner = p->top + 1;
+ sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
upb_sink_startseq(&p->top->sink, sel, &inner->sink);
inner->m = p->top->m;
inner->f = p->top->f;
@@ -1011,10 +1056,12 @@ static bool start_array(upb_json_parser *p) {
}
static void end_array(upb_json_parser *p) {
+ upb_selector_t sel;
+
assert(p->top > p->stack);
p->top--;
- upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
+ sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
upb_sink_endseq(&p->top->sink, sel);
}
@@ -1037,20 +1084,20 @@ static void end_object(upb_json_parser *p) {
/* The actual parser **********************************************************/
-// What follows is the Ragel parser itself. The language is specified in Ragel
-// and the actions call our C functions above.
-//
-// Ragel has an extensive set of functionality, and we use only a small part of
-// it. There are many action types but we only use a few:
-//
-// ">" -- transition into a machine
-// "%" -- transition out of a machine
-// "@" -- transition into a final state of a machine.
-//
-// "@" transitions are tricky because a machine can transition into a final
-// state repeatedly. But in some cases we know this can't happen, for example
-// a string which is delimited by a final '"' can only transition into its
-// final state once, when the closing '"' is seen.
+/* What follows is the Ragel parser itself. The language is specified in Ragel
+ * and the actions call our C functions above.
+ *
+ * Ragel has an extensive set of functionality, and we use only a small part of
+ * it. There are many action types but we only use a few:
+ *
+ * ">" -- transition into a machine
+ * "%" -- transition out of a machine
+ * "@" -- transition into a final state of a machine.
+ *
+ * "@" transitions are tricky because a machine can transition into a final
+ * state repeatedly. But in some cases we know this can't happen, for example
+ * a string which is delimited by a final '"' can only transition into its
+ * final state once, when the closing '"' is seen. */
%%{
machine json;
@@ -1154,12 +1201,9 @@ static void end_object(upb_json_parser *p) {
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
- UPB_UNUSED(hd);
- UPB_UNUSED(handle);
upb_json_parser *parser = closure;
- parser->handle = handle;
- // Variables used by Ragel's generated code.
+ /* Variables used by Ragel's generated code. */
int cs = parser->current_state;
int *stack = parser->parser_stack;
int top = parser->parser_top;
@@ -1167,6 +1211,11 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const char *p = buf;
const char *pe = buf + size;
+ parser->handle = handle;
+
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
capture_resume(parser, buf);
%% write exec;
@@ -1178,7 +1227,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
}
error:
- // Save parsing state back to parser.
+ /* Save parsing state back to parser. */
parser->current_state = cs;
parser->parser_top = top;
@@ -1189,7 +1238,7 @@ bool end(void *closure, const void *hd) {
UPB_UNUSED(closure);
UPB_UNUSED(hd);
- // Prevent compile warning on unused static constants.
+ /* Prevent compile warning on unused static constants. */
UPB_UNUSED(json_start);
UPB_UNUSED(json_en_number_machine);
UPB_UNUSED(json_en_string_machine);
@@ -1199,14 +1248,15 @@ bool end(void *closure, const void *hd) {
}
static void json_parser_reset(upb_json_parser *p) {
+ int cs;
+ int top;
+
p->top = p->stack;
p->top->f = NULL;
p->top->is_map = false;
p->top->is_mapentry = false;
- int cs;
- int top;
- // Emit Ragel initialization of the parser.
+ /* Emit Ragel initialization of the parser. */
%% write init;
p->current_state = cs;
p->parser_top = top;
@@ -1239,8 +1289,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
upb_sink_reset(&p->top->sink, output->handlers, output->closure);
p->top->m = upb_handlers_msgdef(output->handlers);
- // If this fails, uncomment and increase the value in parser.h.
- // fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before);
+ /* If this fails, uncomment and increase the value in parser.h.
+ * fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
return p;
}
diff --git a/upb/json/printer.c b/upb/json/printer.c
index 539f83a..7e52dc2 100644
--- a/upb/json/printer.c
+++ b/upb/json/printer.c
@@ -17,26 +17,26 @@
struct upb_json_printer {
upb_sink input_;
- // BytesSink closure.
+ /* BytesSink closure. */
void *subc_;
upb_bytessink *output_;
- // We track the depth so that we know when to emit startstr/endstr on the
- // output.
+ /* We track the depth so that we know when to emit startstr/endstr on the
+ * output. */
int depth_;
- // Have we emitted the first element? This state is necessary to emit commas
- // without leaving a trailing comma in arrays/maps. We keep this state per
- // frame depth.
- //
- // Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
- // We count frames (contexts in which we separate elements by commas) as both
- // repeated fields and messages (maps), and the worst case is a
- // message->repeated field->submessage->repeated field->... nesting.
+ /* Have we emitted the first element? This state is necessary to emit commas
+ * without leaving a trailing comma in arrays/maps. We keep this state per
+ * frame depth.
+ *
+ * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
+ * We count frames (contexts in which we separate elements by commas) as both
+ * repeated fields and messages (maps), and the worst case is a
+ * message->repeated field->submessage->repeated field->... nesting. */
bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
};
-// StringPiece; a pointer plus a length.
+/* StringPiece; a pointer plus a length. */
typedef struct {
const char *ptr;
size_t len;
@@ -50,11 +50,11 @@ strpc *newstrpc(upb_handlers *h, const upb_fielddef *f) {
return ret;
}
-// ------------ JSON string printing: values, maps, arrays --------------------
+/* ------------ JSON string printing: values, maps, arrays ------------------ */
static void print_data(
upb_json_printer *p, const char *buf, unsigned int len) {
- // TODO: Will need to change if we support pushback from the sink.
+ /* TODO: Will need to change if we support pushback from the sink. */
size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
UPB_ASSERT_VAR(n, n == len);
}
@@ -66,18 +66,18 @@ static void print_comma(upb_json_printer *p) {
p->first_elem_[p->depth_] = false;
}
-// Helpers that print properly formatted elements to the JSON output stream.
+/* Helpers that print properly formatted elements to the JSON output stream. */
-// Used for escaping control chars in strings.
+/* Used for escaping control chars in strings. */
static const char kControlCharLimit = 0x20;
-static inline bool is_json_escaped(char c) {
- // See RFC 4627.
+UPB_INLINE bool is_json_escaped(char c) {
+ /* See RFC 4627. */
unsigned char uc = (unsigned char)c;
return uc < kControlCharLimit || uc == '"' || uc == '\\';
}
-static inline char* json_nice_escape(char c) {
+UPB_INLINE char* json_nice_escape(char c) {
switch (c) {
case '"': return "\\\"";
case '\\': return "\\\\";
@@ -90,46 +90,47 @@ static inline char* json_nice_escape(char c) {
}
}
-// Write a properly escaped string chunk. The surrounding quotes are *not*
-// printed; this is so that the caller has the option of emitting the string
-// content in chunks.
+/* Write a properly escaped string chunk. The surrounding quotes are *not*
+ * printed; this is so that the caller has the option of emitting the string
+ * content in chunks. */
static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
const char* unescaped_run = NULL;
- for (unsigned int i = 0; i < len; i++) {
+ unsigned int i;
+ for (i = 0; i < len; i++) {
char c = buf[i];
- // Handle escaping.
+ /* Handle escaping. */
if (is_json_escaped(c)) {
- // Use a "nice" escape, like \n, if one exists for this character.
+ /* Use a "nice" escape, like \n, if one exists for this character. */
const char* escape = json_nice_escape(c);
- // If we don't have a specific 'nice' escape code, use a \uXXXX-style
- // escape.
+ /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
+ * escape. */
char escape_buf[8];
if (!escape) {
unsigned char byte = (unsigned char)c;
- snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
+ _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
escape = escape_buf;
}
- // N.B. that we assume that the input encoding is equal to the output
- // encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we
- // can simply pass the bytes through.
+ /* N.B. that we assume that the input encoding is equal to the output
+ * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we
+ * can simply pass the bytes through. */
- // If there's a current run of unescaped chars, print that run first.
+ /* If there's a current run of unescaped chars, print that run first. */
if (unescaped_run) {
print_data(p, unescaped_run, &buf[i] - unescaped_run);
unescaped_run = NULL;
}
- // Then print the escape code.
+ /* Then print the escape code. */
print_data(p, escape, strlen(escape));
} else {
- // Add to the current unescaped run of characters.
+ /* Add to the current unescaped run of characters. */
if (unescaped_run == NULL) {
unescaped_run = &buf[i];
}
}
}
- // If the string ended in a run of unescaped characters, print that last run.
+ /* If the string ended in a run of unescaped characters, print that last run. */
if (unescaped_run) {
print_data(p, unescaped_run, &buf[len] - unescaped_run);
}
@@ -137,42 +138,42 @@ static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
#define CHKLENGTH(x) if (!(x)) return -1;
-// Helpers that format floating point values according to our custom formats.
-// Right now we use %.8g and %.17g for float/double, respectively, to match
-// proto2::util::JsonFormat's defaults. May want to change this later.
+/* Helpers that format floating point values according to our custom formats.
+ * Right now we use %.8g and %.17g for float/double, respectively, to match
+ * proto2::util::JsonFormat's defaults. May want to change this later. */
static size_t fmt_double(double val, char* buf, size_t length) {
- size_t n = snprintf(buf, length, "%.17g", val);
+ size_t n = _upb_snprintf(buf, length, "%.17g", val);
CHKLENGTH(n > 0 && n < length);
return n;
}
static size_t fmt_float(float val, char* buf, size_t length) {
- size_t n = snprintf(buf, length, "%.8g", val);
+ size_t n = _upb_snprintf(buf, length, "%.8g", val);
CHKLENGTH(n > 0 && n < length);
return n;
}
static size_t fmt_bool(bool val, char* buf, size_t length) {
- size_t n = snprintf(buf, length, "%s", (val ? "true" : "false"));
+ size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
CHKLENGTH(n > 0 && n < length);
return n;
}
static size_t fmt_int64(long val, char* buf, size_t length) {
- size_t n = snprintf(buf, length, "%ld", val);
+ size_t n = _upb_snprintf(buf, length, "%ld", val);
CHKLENGTH(n > 0 && n < length);
return n;
}
static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) {
- size_t n = snprintf(buf, length, "%llu", val);
+ size_t n = _upb_snprintf(buf, length, "%llu", val);
CHKLENGTH(n > 0 && n < length);
return n;
}
-// Print a map key given a field name. Called by scalar field handlers and by
-// startseq for repeated fields.
+/* Print a map key given a field name. Called by scalar field handlers and by
+ * startseq for repeated fields. */
static bool putkey(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
const strpc *key = handler_data;
@@ -189,9 +190,9 @@ static bool putkey(void *closure, const void *handler_data) {
#define TYPE_HANDLERS(type, fmt_func) \
static bool put##type(void *closure, const void *handler_data, type val) { \
upb_json_printer *p = closure; \
- UPB_UNUSED(handler_data); \
char data[64]; \
size_t length = fmt_func(val, data, sizeof(data)); \
+ UPB_UNUSED(handler_data); \
CHKFMT(length); \
print_data(p, data, length); \
return true; \
@@ -220,20 +221,20 @@ static bool putkey(void *closure, const void *handler_data) {
return true; \
}
-TYPE_HANDLERS(double, fmt_double);
-TYPE_HANDLERS(float, fmt_float);
-TYPE_HANDLERS(bool, fmt_bool);
-TYPE_HANDLERS(int32_t, fmt_int64);
-TYPE_HANDLERS(uint32_t, fmt_int64);
-TYPE_HANDLERS(int64_t, fmt_int64);
-TYPE_HANDLERS(uint64_t, fmt_uint64);
-
-// double and float are not allowed to be map keys.
-TYPE_HANDLERS_MAPKEY(bool, fmt_bool);
-TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64);
-TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64);
-TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64);
-TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64);
+TYPE_HANDLERS(double, fmt_double)
+TYPE_HANDLERS(float, fmt_float)
+TYPE_HANDLERS(bool, fmt_bool)
+TYPE_HANDLERS(int32_t, fmt_int64)
+TYPE_HANDLERS(uint32_t, fmt_int64)
+TYPE_HANDLERS(int64_t, fmt_int64)
+TYPE_HANDLERS(uint64_t, fmt_uint64)
+
+/* double and float are not allowed to be map keys. */
+TYPE_HANDLERS_MAPKEY(bool, fmt_bool)
+TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64)
+TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64)
+TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64)
#undef TYPE_HANDLERS
#undef TYPE_HANDLERS_MAPKEY
@@ -247,9 +248,11 @@ static bool scalar_enum(void *closure, const void *handler_data,
int32_t val) {
const EnumHandlerData *hd = handler_data;
upb_json_printer *p = closure;
+ const char *symbolic_name;
+
CHK(putkey(closure, hd->keyname));
- const char *symbolic_name = upb_enumdef_iton(hd->enumdef, val);
+ symbolic_name = upb_enumdef_iton(hd->enumdef, val);
if (symbolic_name) {
print_data(p, "\"", 1);
putstring(p, symbolic_name, strlen(symbolic_name));
@@ -300,8 +303,8 @@ static void *scalar_startsubmsg(void *closure, const void *handler_data) {
}
static void *repeated_startsubmsg(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_comma(p);
return closure;
}
@@ -318,8 +321,8 @@ static void end_frame(upb_json_printer *p) {
}
static bool printer_startmsg(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
if (p->depth_ == 0) {
upb_bytessink_start(p->output_, 0, &p->subc_);
}
@@ -328,9 +331,9 @@ static bool printer_startmsg(void *closure, const void *handler_data) {
}
static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
+ upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(s);
- upb_json_printer *p = closure;
end_frame(p);
if (p->depth_ == 0) {
upb_bytessink_end(p->output_);
@@ -348,8 +351,8 @@ static void *startseq(void *closure, const void *handler_data) {
}
static bool endseq(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "]", 1);
p->depth_--;
return true;
@@ -365,8 +368,8 @@ static void *startmap(void *closure, const void *handler_data) {
}
static bool endmap(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "}", 1);
p->depth_--;
return true;
@@ -374,32 +377,35 @@ static bool endmap(void *closure, const void *handler_data) {
static size_t putstr(void *closure, const void *handler_data, const char *str,
size_t len, const upb_bufhandle *handle) {
+ upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(handle);
- upb_json_printer *p = closure;
putstring(p, str, len);
return len;
}
-// This has to Base64 encode the bytes, because JSON has no "bytes" type.
+/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
static size_t putbytes(void *closure, const void *handler_data, const char *str,
size_t len, const upb_bufhandle *handle) {
- UPB_UNUSED(handler_data);
- UPB_UNUSED(handle);
upb_json_printer *p = closure;
- // This is the regular base64, not the "web-safe" version.
+ /* This is the regular base64, not the "web-safe" version. */
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- // Base64-encode.
+ /* Base64-encode. */
char data[16000];
const char *limit = data + sizeof(data);
const unsigned char *from = (const unsigned char*)str;
char *to = data;
size_t remaining = len;
+ size_t bytes;
+
+ UPB_UNUSED(handler_data);
+ UPB_UNUSED(handle);
+
while (remaining > 2) {
- // TODO(haberman): handle encoded lengths > sizeof(data)
+ /* TODO(haberman): handle encoded lengths > sizeof(data) */
UPB_ASSERT_VAR(limit, (limit - to) >= 4);
to[0] = base64[from[0] >> 2];
@@ -431,7 +437,7 @@ static size_t putbytes(void *closure, const void *handler_data, const char *str,
break;
}
- size_t bytes = to - data;
+ bytes = to - data;
print_data(p, "\"", 1);
putstring(p, data, bytes);
print_data(p, "\"", 1);
@@ -440,9 +446,9 @@ static size_t putbytes(void *closure, const void *handler_data, const char *str,
static void *scalar_startstr(void *closure, const void *handler_data,
size_t size_hint) {
+ upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
- upb_json_printer *p = closure;
CHK(putkey(closure, handler_data));
print_data(p, "\"", 1);
return p;
@@ -456,17 +462,17 @@ static size_t scalar_str(void *closure, const void *handler_data,
}
static bool scalar_endstr(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "\"", 1);
return true;
}
static void *repeated_startstr(void *closure, const void *handler_data,
size_t size_hint) {
+ upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
- upb_json_printer *p = closure;
print_comma(p);
print_data(p, "\"", 1);
return p;
@@ -480,17 +486,17 @@ static size_t repeated_str(void *closure, const void *handler_data,
}
static bool repeated_endstr(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "\"", 1);
return true;
}
static void *mapkeyval_startstr(void *closure, const void *handler_data,
size_t size_hint) {
+ upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
- upb_json_printer *p = closure;
print_data(p, "\"", 1);
return p;
}
@@ -503,15 +509,15 @@ static size_t mapkey_str(void *closure, const void *handler_data,
}
static bool mapkey_endstr(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "\":", 2);
return true;
}
static bool mapvalue_endstr(void *closure, const void *handler_data) {
- UPB_UNUSED(handler_data);
upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
print_data(p, "\"", 1);
return true;
}
@@ -552,30 +558,31 @@ static void set_enum_hd(upb_handlers *h,
upb_handlerattr_sethandlerdata(attr, hd);
}
-// Set up handlers for a mapentry submessage (i.e., an individual key/value pair
-// in a map).
-//
-// TODO: Handle missing key, missing value, out-of-order key/value, or repeated
-// key or value cases properly. The right way to do this is to allocate a
-// temporary structure at the start of a mapentry submessage, store key and
-// value data in it as key and value handlers are called, and then print the
-// key/value pair once at the end of the submessage. If we don't do this, we
-// should at least detect the case and throw an error. However, so far all of
-// our sources that emit mapentry messages do so canonically (with one key
-// field, and then one value field), so this is not a pressing concern at the
-// moment.
+/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
+ * in a map).
+ *
+ * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
+ * key or value cases properly. The right way to do this is to allocate a
+ * temporary structure at the start of a mapentry submessage, store key and
+ * value data in it as key and value handlers are called, and then print the
+ * key/value pair once at the end of the submessage. If we don't do this, we
+ * should at least detect the case and throw an error. However, so far all of
+ * our sources that emit mapentry messages do so canonically (with one key
+ * field, and then one value field), so this is not a pressing concern at the
+ * moment. */
void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
- UPB_UNUSED(closure);
const upb_msgdef *md = upb_handlers_msgdef(h);
- // A mapentry message is printed simply as '"key": value'. Rather than
- // special-case key and value for every type below, we just handle both
- // fields explicitly here.
+ /* A mapentry message is printed simply as '"key": value'. Rather than
+ * special-case key and value for every type below, we just handle both
+ * fields explicitly here. */
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_UNUSED(closure);
+
switch (upb_fielddef_type(key_field)) {
case UPB_TYPE_INT32:
upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
@@ -643,8 +650,8 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
break;
}
case UPB_TYPE_MESSAGE:
- // No handler necessary -- the submsg handlers will print the message
- // as appropriate.
+ /* No handler necessary -- the submsg handlers will print the message
+ * as appropriate. */
break;
}
@@ -652,14 +659,16 @@ void printer_sethandlers_mapentry(const void *closure, upb_handlers *h) {
}
void printer_sethandlers(const void *closure, upb_handlers *h) {
- UPB_UNUSED(closure);
const upb_msgdef *md = upb_handlers_msgdef(h);
bool is_mapentry = upb_msgdef_mapentry(md);
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_msg_field_iter i;
+
+ UPB_UNUSED(closure);
if (is_mapentry) {
- // mapentry messages are sufficiently different that we handle them
- // separately.
+ /* mapentry messages are sufficiently different that we handle them
+ * separately. */
printer_sethandlers_mapentry(closure, h);
return;
}
@@ -676,7 +685,6 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
} \
break;
- upb_msg_field_iter i;
upb_msg_field_begin(&i, md);
for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
@@ -701,9 +709,9 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
TYPE(UPB_TYPE_INT64, int64, int64_t);
TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
case UPB_TYPE_ENUM: {
- // 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.
+ /* 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;
set_enum_hd(h, f, &enum_attr);
@@ -728,8 +736,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
}
break;
case UPB_TYPE_BYTES:
- // XXX: this doesn't support strings that span buffers yet. The base64
- // encoder will need to be made resumable for this to work properly.
+ /* XXX: this doesn't support strings that span buffers yet. The base64
+ * encoder will need to be made resumable for this to work properly. */
if (upb_fielddef_isseq(f)) {
upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
} else {
@@ -772,7 +780,7 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
json_printer_reset(p);
upb_sink_reset(&p->input_, h, p);
- // If this fails, increase the value in printer.h.
+ /* If this fails, increase the value in printer.h. */
assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
return p;
}
diff --git a/upb/json/printer.h b/upb/json/printer.h
index c73cb79..0b4e19c 100644
--- a/upb/json/printer.h
+++ b/upb/json/printer.h
@@ -18,11 +18,11 @@
namespace upb {
namespace json {
class Printer;
-} // namespace json
-} // namespace upb
+} /* namespace json */
+} /* namespace upb */
#endif
-UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer);
+UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer)
/* upb::json::Printer *********************************************************/
@@ -31,29 +31,29 @@ UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer);
#ifdef __cplusplus
-// Prints an incoming stream of data to a BytesSink in JSON format.
+/* Prints an incoming stream of data to a BytesSink in JSON format. */
class upb::json::Printer {
public:
static Printer* Create(Environment* env, const upb::Handlers* handlers,
BytesSink* output);
- // The input to the printer.
+ /* The input to the printer. */
Sink* input();
- // Returns handlers for printing according to the specified schema.
+ /* Returns handlers for printing according to the specified schema. */
static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md);
static const size_t kSize = UPB_JSON_PRINTER_SIZE;
private:
- UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer);
+ UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer)
};
#endif
UPB_BEGIN_EXTERN_C
-// Native C API.
+/* 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);
@@ -76,9 +76,9 @@ inline reffed_ptr<const Handlers> Printer::NewHandlers(
const Handlers* h = upb_json_printer_newhandlers(md, &h);
return reffed_ptr<const Handlers>(h, &h);
}
-} // namespace json
-} // namespace upb
+} /* namespace json */
+} /* namespace upb */
#endif
-#endif // UPB_JSON_TYPED_PRINTER_H_
+#endif /* UPB_JSON_TYPED_PRINTER_H_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback