Merge pull request #234 from haberman/parser

Removed upb_decframe structure and used explicit pointer param/return
pull/13171/head
Joshua Haberman 5 years ago committed by GitHub
commit a202c5f84d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      generated_for_cmake/upb/json/parser.c
  2. 409
      upb/decode.c
  3. 2
      upb/def.c
  4. 6
      upb/json/parser.rl
  5. 4
      upb/pb/compile_decoder.c
  6. 12
      upb/port_def.inc
  7. 1
      upb/port_undef.inc

@ -391,7 +391,7 @@ static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
upb_handlertype_t type) { upb_handlertype_t type) {
upb_selector_t sel; upb_selector_t sel;
bool ok = upb_handlers_getselector(p->top->f, type, &sel); bool ok = upb_handlers_getselector(p->top->f, type, &sel);
UPB_ASSERT(ok); UPB_ASSUME(ok);
return sel; return sel;
} }
@ -416,7 +416,7 @@ static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
const upb_json_parsermethod *method; const upb_json_parsermethod *method;
ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
UPB_ASSERT(ok); UPB_ASSUME(ok);
method = upb_value_getconstptr(v); method = upb_value_getconstptr(v);
frame->name_table = &method->name_table; frame->name_table = &method->name_table;
@ -2021,7 +2021,7 @@ static void end_member(upb_json_parser *p) {
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */ /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--; p->top--;
ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT(ok); UPB_ASSUME(ok);
upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel); upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
} }

@ -53,7 +53,6 @@ static const uint8_t desctype_to_mapsize[] = {
/* Data pertaining to the parse. */ /* Data pertaining to the parse. */
typedef struct { typedef struct {
const char *ptr; /* Current parsing position. */
const char *field_start; /* Start of this field. */ const char *field_start; /* Start of this field. */
const char *limit; /* End of delimited region or end of buffer. */ const char *limit; /* End of delimited region or end of buffer. */
upb_arena *arena; upb_arena *arena;
@ -61,60 +60,52 @@ typedef struct {
uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */ uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */
} upb_decstate; } upb_decstate;
/* Data passed by value to each parsing function. */
typedef struct {
char *msg;
const upb_msglayout *layout;
upb_decstate *state;
} upb_decframe;
#define CHK(x) if (!(x)) { return 0; } #define CHK(x) if (!(x)) { return 0; }
#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
static bool upb_skip_unknowngroup(upb_decstate *d, int field_number); static const char *upb_skip_unknowngroup(const char *ptr, upb_decstate *d,
static bool upb_decode_message(upb_decstate *d, char *msg, int field_number);
const upb_msglayout *l); static const char *upb_decode_message(const char *ptr, const upb_msglayout *l,
upb_msg *msg, upb_decstate *d);
static bool upb_decode_varint(const char **ptr, const char *limit, static const char *upb_decode_varint(const char *ptr, const char *limit,
uint64_t *val) { uint64_t *val) {
uint8_t byte; uint8_t byte;
int bitpos = 0; int bitpos = 0;
const char *p = *ptr;
*val = 0; *val = 0;
do { do {
CHK(bitpos < 70 && p < limit); CHK(bitpos < 70 && ptr < limit);
byte = *p; byte = *ptr;
*val |= (uint64_t)(byte & 0x7F) << bitpos; *val |= (uint64_t)(byte & 0x7F) << bitpos;
p++; ptr++;
bitpos += 7; bitpos += 7;
} while (byte & 0x80); } while (byte & 0x80);
*ptr = p; return ptr;
return true;
} }
static bool upb_decode_varint32(const char **ptr, const char *limit, static const char *upb_decode_varint32(const char *ptr, const char *limit,
uint32_t *val) { uint32_t *val) {
uint64_t u64; uint64_t u64;
CHK(upb_decode_varint(ptr, limit, &u64) && u64 <= UINT32_MAX); CHK(ptr = upb_decode_varint(ptr, limit, &u64))
CHK(u64 <= UINT32_MAX);
*val = (uint32_t)u64; *val = (uint32_t)u64;
return true; return ptr;
} }
static bool upb_decode_64bit(const char **ptr, const char *limit, static const char *upb_decode_64bit(const char *ptr, const char *limit,
uint64_t *val) { uint64_t *val) {
CHK(limit - *ptr >= 8); CHK(limit - ptr >= 8);
memcpy(val, *ptr, 8); memcpy(val, ptr, 8);
*ptr += 8; return ptr + 8;
return true;
} }
static bool upb_decode_32bit(const char **ptr, const char *limit, static const char *upb_decode_32bit(const char *ptr, const char *limit,
uint32_t *val) { uint32_t *val) {
CHK(limit - *ptr >= 4); CHK(limit - ptr >= 4);
memcpy(val, *ptr, 4); memcpy(val, ptr, 4);
*ptr += 4; return ptr + 4;
return true;
} }
static int32_t upb_zzdecode_32(uint32_t n) { static int32_t upb_zzdecode_32(uint32_t n) {
@ -125,68 +116,68 @@ static int64_t upb_zzdecode_64(uint64_t n) {
return (n >> 1) ^ -(int64_t)(n & 1); return (n >> 1) ^ -(int64_t)(n & 1);
} }
static bool upb_decode_string(const char **ptr, const char *limit, static const char *upb_decode_string(const char *ptr, const char *limit,
int *outlen) { int *outlen) {
uint32_t len; uint32_t len;
CHK(upb_decode_varint32(ptr, limit, &len) && CHK(ptr = upb_decode_varint32(ptr, limit, &len));
len < INT32_MAX && CHK(len < INT32_MAX);
limit - *ptr >= (int32_t)len); CHK(limit - ptr >= (int32_t)len);
*outlen = len; *outlen = len;
return true; return ptr;
} }
static void upb_set32(void *msg, size_t ofs, uint32_t val) { static void upb_set32(void *msg, size_t ofs, uint32_t val) {
memcpy((char*)msg + ofs, &val, sizeof(val)); memcpy((char*)msg + ofs, &val, sizeof(val));
} }
static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame) { static const char *upb_append_unknown(const char *ptr, upb_msg *msg, upb_decstate *d) {
upb_msg_addunknown(frame->msg, d->field_start, d->ptr - d->field_start, upb_msg_addunknown(msg, d->field_start, ptr - d->field_start, d->arena);
d->arena); return ptr;
return true;
} }
static const char *upb_skip_unknownfielddata(const char *ptr, upb_decstate *d,
static bool upb_skip_unknownfielddata(upb_decstate *d, uint32_t tag, uint32_t tag,
uint32_t group_fieldnum) { uint32_t group_fieldnum) {
switch (tag & 7) { switch (tag & 7) {
case UPB_WIRE_TYPE_VARINT: { case UPB_WIRE_TYPE_VARINT: {
uint64_t val; uint64_t val;
return upb_decode_varint(&d->ptr, d->limit, &val); return upb_decode_varint(ptr, d->limit, &val);
} }
case UPB_WIRE_TYPE_32BIT: { case UPB_WIRE_TYPE_32BIT: {
uint32_t val; uint32_t val;
return upb_decode_32bit(&d->ptr, d->limit, &val); return upb_decode_32bit(ptr, d->limit, &val);
} }
case UPB_WIRE_TYPE_64BIT: { case UPB_WIRE_TYPE_64BIT: {
uint64_t val; uint64_t val;
return upb_decode_64bit(&d->ptr, d->limit, &val); return upb_decode_64bit(ptr, d->limit, &val);
} }
case UPB_WIRE_TYPE_DELIMITED: { case UPB_WIRE_TYPE_DELIMITED: {
int len; int len;
CHK(upb_decode_string(&d->ptr, d->limit, &len)); CHK(ptr = upb_decode_string(ptr, d->limit, &len));
d->ptr += len; return ptr + len;
return true;
} }
case UPB_WIRE_TYPE_START_GROUP: case UPB_WIRE_TYPE_START_GROUP:
return upb_skip_unknowngroup(d, tag >> 3); return upb_skip_unknowngroup(ptr, d, tag >> 3);
case UPB_WIRE_TYPE_END_GROUP: case UPB_WIRE_TYPE_END_GROUP:
return (tag >> 3) == group_fieldnum; CHK((tag >> 3) == group_fieldnum);
return ptr;
} }
return false; return false;
} }
static bool upb_skip_unknowngroup(upb_decstate *d, int field_number) { static const char *upb_skip_unknowngroup(const char *ptr, upb_decstate *d,
while (d->ptr < d->limit && d->end_group == 0) { int field_number) {
while (ptr < d->limit && d->end_group == 0) {
uint32_t tag = 0; uint32_t tag = 0;
CHK(upb_decode_varint32(&d->ptr, d->limit, &tag)); CHK(ptr = upb_decode_varint32(ptr, d->limit, &tag));
CHK(upb_skip_unknownfielddata(d, tag, field_number)); CHK(ptr = upb_skip_unknownfielddata(ptr, d, tag, field_number));
} }
CHK(d->end_group == field_number); CHK(d->end_group == field_number);
d->end_group = 0; d->end_group = 0;
return true; return ptr;
} }
static void *upb_array_reserve(upb_array *arr, size_t elements, static void *upb_array_reserve(upb_array *arr, size_t elements,
@ -208,83 +199,80 @@ bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size,
return true; return true;
} }
static upb_array *upb_getarr(upb_decframe *frame, static upb_array *upb_getarr(upb_msg *msg, const upb_msglayout_field *field) {
const upb_msglayout_field *field) {
UPB_ASSERT(field->label == UPB_LABEL_REPEATED); UPB_ASSERT(field->label == UPB_LABEL_REPEATED);
return *(upb_array**)&frame->msg[field->offset]; return *PTR_AT(msg, field->offset, upb_array*);
} }
static upb_array *upb_getorcreatearr(upb_decframe *frame, static upb_array *upb_getorcreatearr(upb_msg *msg,
const upb_msglayout_field *field) { const upb_msglayout_field *field,
upb_array *arr = upb_getarr(frame, field); upb_decstate *d) {
upb_array *arr = upb_getarr(msg, field);
if (!arr) { if (!arr) {
upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype]; upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype];
arr = _upb_array_new(frame->state->arena, type); arr = _upb_array_new(d->arena, type);
CHK(arr); CHK(arr);
*(upb_array**)&frame->msg[field->offset] = arr; *PTR_AT(msg, field->offset, upb_array*) = arr;
} }
return arr; return arr;
} }
static upb_msg *upb_getorcreatemsg(upb_decframe *frame, static upb_msg *upb_getorcreatemsg(upb_msg *msg,
const upb_msglayout_field *field, const upb_msglayout_field *field,
const upb_msglayout **subm) { const upb_msglayout *layout,
upb_msg **submsg = (void*)(frame->msg + field->offset); upb_decstate *d) {
*subm = frame->layout->submsgs[field->submsg_index]; upb_msg **submsg = PTR_AT(msg, field->offset, upb_msg*);
UPB_ASSERT(field->label != UPB_LABEL_REPEATED); UPB_ASSERT(field->label != UPB_LABEL_REPEATED);
if (!*submsg) { if (!*submsg) {
*submsg = _upb_msg_new(*subm, frame->state->arena); *submsg = _upb_msg_new(layout, d->arena);
CHK(*submsg); CHK(*submsg);
} }
return *submsg; return *submsg;
} }
static upb_msg *upb_addmsg(upb_decframe *frame, static upb_msg *upb_addmsg(upb_msg *msg,
const upb_msglayout_field *field, const upb_msglayout_field *field,
const upb_msglayout **subm) { const upb_msglayout *layout,
upb_decstate *d) {
upb_msg *submsg; upb_msg *submsg;
upb_array *arr = upb_getorcreatearr(frame, field); upb_array *arr = upb_getorcreatearr(msg, field, d);
UPB_ASSERT(field->label == UPB_LABEL_REPEATED); UPB_ASSERT(field->label == UPB_LABEL_REPEATED);
UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE || UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP); field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
*subm = frame->layout->submsgs[field->submsg_index]; submsg = _upb_msg_new(layout, d->arena);
submsg = _upb_msg_new(*subm, frame->state->arena);
CHK(submsg); CHK(submsg);
upb_array_add(arr, 1, sizeof(submsg), &submsg, frame->state->arena); upb_array_add(arr, 1, sizeof(submsg), &submsg, d->arena);
return submsg; return submsg;
} }
static void upb_sethasbit(upb_decframe *frame, static void upb_sethasbit(upb_msg *msg, const upb_msglayout_field *field) {
const upb_msglayout_field *field) {
int32_t hasbit = field->presence; int32_t hasbit = field->presence;
UPB_ASSERT(field->presence > 0); UPB_ASSERT(field->presence > 0);
frame->msg[hasbit / 8] |= (1 << (hasbit % 8)); *PTR_AT(msg, hasbit / 8, char) |= (1 << (hasbit % 8));
} }
static void upb_setoneofcase(upb_decframe *frame, static void upb_setoneofcase(upb_msg *msg, const upb_msglayout_field *field) {
const upb_msglayout_field *field) {
UPB_ASSERT(field->presence < 0); UPB_ASSERT(field->presence < 0);
upb_set32(frame->msg, ~field->presence, field->number); upb_set32(msg, ~field->presence, field->number);
} }
static bool upb_decode_addval(upb_decframe *frame, static bool upb_decode_addval(upb_msg *msg, const upb_msglayout_field *field,
const upb_msglayout_field *field, void *val, void *val, size_t size, upb_decstate *d) {
size_t size) { char *field_mem = PTR_AT(msg, field->offset, char);
char *field_mem = frame->msg + field->offset;
upb_array *arr; upb_array *arr;
if (field->label == UPB_LABEL_REPEATED) { if (field->label == UPB_LABEL_REPEATED) {
arr = upb_getorcreatearr(frame, field); arr = upb_getorcreatearr(msg, field, d);
CHK(arr); CHK(arr);
field_mem = upb_array_reserve(arr, 1, size, frame->state->arena); field_mem = upb_array_reserve(arr, 1, size, d->arena);
CHK(field_mem); CHK(field_mem);
} }
@ -292,142 +280,147 @@ static bool upb_decode_addval(upb_decframe *frame,
return true; return true;
} }
static void upb_decode_setpresent(upb_decframe *frame, static void upb_decode_setpresent(upb_msg *msg,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
if (field->label == UPB_LABEL_REPEATED) { if (field->label == UPB_LABEL_REPEATED) {
upb_array *arr = upb_getarr(frame, field); upb_array *arr = upb_getarr(msg, field);
UPB_ASSERT(arr->len < arr->size); UPB_ASSERT(arr->len < arr->size);
arr->len++; arr->len++;
} else if (field->presence < 0) { } else if (field->presence < 0) {
upb_setoneofcase(frame, field); upb_setoneofcase(msg, field);
} else if (field->presence > 0) { } else if (field->presence > 0) {
upb_sethasbit(frame, field); upb_sethasbit(msg, field);
} }
} }
static bool upb_decode_msgfield(upb_decstate *d, upb_msg *msg, static const char *upb_decode_msgfield(const char *ptr,
const upb_msglayout *layout, int limit) { const upb_msglayout *layout, int limit,
upb_msg *msg, upb_decstate *d) {
const char* saved_limit = d->limit; const char* saved_limit = d->limit;
d->limit = d->ptr + limit; d->limit = ptr + limit;
CHK(--d->depth >= 0); CHK(--d->depth >= 0);
upb_decode_message(d, msg, layout); ptr = upb_decode_message(ptr, layout, msg, d);
d->depth++; d->depth++;
d->limit = saved_limit; d->limit = saved_limit;
CHK(d->end_group == 0); CHK(d->end_group == 0);
return true; return ptr;
} }
static bool upb_decode_groupfield(upb_decstate *d, upb_msg *msg, static const char *upb_decode_groupfield(const char *ptr,
const upb_msglayout *layout, const upb_msglayout *layout,
int field_number) { int field_number, upb_msg *msg,
upb_decstate *d) {
CHK(--d->depth >= 0); CHK(--d->depth >= 0);
upb_decode_message(d, msg, layout); ptr = upb_decode_message(ptr, layout, msg, d);
d->depth++; d->depth++;
CHK(d->end_group == field_number); CHK(d->end_group == field_number);
d->end_group = 0; d->end_group = 0;
return true; return ptr;
} }
static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_varintfield(const char *ptr, upb_msg *msg,
const upb_msglayout_field *field) { const upb_msglayout_field *field,
upb_decstate *d) {
uint64_t val; uint64_t val;
CHK(upb_decode_varint(&d->ptr, d->limit, &val)); CHK(ptr = upb_decode_varint(ptr, d->limit, &val));
switch (field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64: case UPB_DESCRIPTOR_TYPE_UINT64:
CHK(upb_decode_addval(frame, field, &val, sizeof(val))); CHK(upb_decode_addval(msg, field, &val, sizeof(val), d));
break; break;
case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM: { case UPB_DESCRIPTOR_TYPE_ENUM: {
uint32_t val32 = (uint32_t)val; uint32_t val32 = (uint32_t)val;
CHK(upb_decode_addval(frame, field, &val32, sizeof(val32))); CHK(upb_decode_addval(msg, field, &val32, sizeof(val32), d));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_BOOL: { case UPB_DESCRIPTOR_TYPE_BOOL: {
bool valbool = val != 0; bool valbool = val != 0;
CHK(upb_decode_addval(frame, field, &valbool, sizeof(valbool))); CHK(upb_decode_addval(msg, field, &valbool, sizeof(valbool), d));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_SINT32: { case UPB_DESCRIPTOR_TYPE_SINT32: {
int32_t decoded = upb_zzdecode_32((uint32_t)val); int32_t decoded = upb_zzdecode_32((uint32_t)val);
CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded))); CHK(upb_decode_addval(msg, field, &decoded, sizeof(decoded), d));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_SINT64: { case UPB_DESCRIPTOR_TYPE_SINT64: {
int64_t decoded = upb_zzdecode_64(val); int64_t decoded = upb_zzdecode_64(val);
CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded))); CHK(upb_decode_addval(msg, field, &decoded, sizeof(decoded), d));
break; break;
} }
default: default:
return upb_append_unknown(d, frame); return upb_append_unknown(ptr, msg, d);
} }
upb_decode_setpresent(frame, field); upb_decode_setpresent(msg, field);
return true; return ptr;
} }
static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_64bitfield(const char *ptr,
const upb_msglayout_field *field) { const upb_msglayout_field *field,
upb_msg *msg, upb_decstate *d) {
uint64_t val; uint64_t val;
CHK(upb_decode_64bit(&d->ptr, d->limit, &val)); CHK(ptr = upb_decode_64bit(ptr, d->limit, &val));
switch (field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_DOUBLE: case UPB_DESCRIPTOR_TYPE_DOUBLE:
case UPB_DESCRIPTOR_TYPE_FIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64:
case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_SFIXED64:
CHK(upb_decode_addval(frame, field, &val, sizeof(val))); CHK(upb_decode_addval(msg, field, &val, sizeof(val), d));
break; break;
default: default:
return upb_append_unknown(d, frame); return upb_append_unknown(ptr, msg, d);
} }
upb_decode_setpresent(frame, field); upb_decode_setpresent(msg, field);
return true; return ptr;
} }
static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_32bitfield(const char *ptr,
const upb_msglayout_field *field) { const upb_msglayout_field *field,
upb_msg *msg, upb_decstate *d) {
uint32_t val; uint32_t val;
CHK(upb_decode_32bit(&d->ptr, d->limit, &val)); CHK(ptr = upb_decode_32bit(ptr, d->limit, &val));
switch (field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_FLOAT: case UPB_DESCRIPTOR_TYPE_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_FIXED32:
case UPB_DESCRIPTOR_TYPE_SFIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32:
CHK(upb_decode_addval(frame, field, &val, sizeof(val))); CHK(upb_decode_addval(msg, field, &val, sizeof(val), d));
break; break;
default: default:
return upb_append_unknown(d, frame); return upb_append_unknown(ptr, msg, d);
} }
upb_decode_setpresent(frame, field); upb_decode_setpresent(msg, field);
return true; return ptr;
} }
static bool upb_decode_fixedpacked(upb_decstate *d, upb_array *arr, static const char *upb_decode_fixedpacked(const char *ptr, upb_decstate *d,
uint32_t len, int elem_size) { upb_array *arr, uint32_t len,
int elem_size) {
size_t elements = len / elem_size; size_t elements = len / elem_size;
CHK((size_t)(elements * elem_size) == len); CHK((size_t)(elements * elem_size) == len);
CHK(upb_array_add(arr, elements, elem_size, d->ptr, d->arena)); CHK(upb_array_add(arr, elements, elem_size, ptr, d->arena));
d->ptr += len; return ptr + len;
return true;
} }
static upb_strview upb_decode_strfield(upb_decstate *d, uint32_t len) { static const char *upb_decode_strfield(const char *ptr, upb_decstate *d,
upb_strview ret; uint32_t len, upb_strview *str) {
ret.data = d->ptr; str->data = ptr;
ret.size = len; str->size = len;
d->ptr += len; return ptr + len;
return ret;
} }
static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_toarray(const char *ptr,
const upb_msglayout_field *field, int len) { const upb_msglayout *layout,
upb_array *arr = upb_getorcreatearr(frame, field); const upb_msglayout_field *field, int len,
upb_msg *msg, upb_decstate *d) {
upb_array *arr = upb_getorcreatearr(msg, field, d);
CHK(arr); CHK(arr);
#define VARINT_CASE(ctype, decode) \ #define VARINT_CASE(ctype, decode) \
@ -435,33 +428,33 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
#define VARINT_CASE_EX(ctype, decode, dtype) \ #define VARINT_CASE_EX(ctype, decode, dtype) \
{ \ { \
const char *ptr = d->ptr; \
const char *limit = ptr + len; \ const char *limit = ptr + len; \
while (ptr < limit) { \ while (ptr < limit) { \
uint64_t val; \ uint64_t val; \
ctype decoded; \ ctype decoded; \
CHK(upb_decode_varint(&ptr, limit, &val)); \ CHK(ptr = upb_decode_varint(ptr, limit, &val)); \
decoded = (decode)((dtype)val); \ decoded = (decode)((dtype)val); \
CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded, d->arena)); \ CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded, d->arena)); \
} \ } \
d->ptr = ptr; \ return ptr; \
return true; \
} }
switch (field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: { case UPB_DESCRIPTOR_TYPE_BYTES: {
upb_strview str = upb_decode_strfield(d, len); upb_strview str;
return upb_array_add(arr, 1, sizeof(str), &str, d->arena); ptr = upb_decode_strfield(ptr, d, len, &str);
CHK(upb_array_add(arr, 1, sizeof(str), &str, d->arena));
return ptr;
} }
case UPB_DESCRIPTOR_TYPE_FLOAT: case UPB_DESCRIPTOR_TYPE_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_FIXED32:
case UPB_DESCRIPTOR_TYPE_SFIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32:
return upb_decode_fixedpacked(d, arr, len, sizeof(int32_t)); return upb_decode_fixedpacked(ptr, d, arr, len, sizeof(int32_t));
case UPB_DESCRIPTOR_TYPE_DOUBLE: case UPB_DESCRIPTOR_TYPE_DOUBLE:
case UPB_DESCRIPTOR_TYPE_FIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64:
case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_SFIXED64:
return upb_decode_fixedpacked(d, arr, len, sizeof(int64_t)); return upb_decode_fixedpacked(ptr, d, arr, len, sizeof(int64_t));
case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM: case UPB_DESCRIPTOR_TYPE_ENUM:
@ -476,22 +469,24 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
case UPB_DESCRIPTOR_TYPE_SINT64: case UPB_DESCRIPTOR_TYPE_SINT64:
VARINT_CASE_EX(int64_t, upb_zzdecode_64, uint64_t); VARINT_CASE_EX(int64_t, upb_zzdecode_64, uint64_t);
case UPB_DESCRIPTOR_TYPE_MESSAGE: { case UPB_DESCRIPTOR_TYPE_MESSAGE: {
const upb_msglayout *subm; const upb_msglayout *subl = layout->submsgs[field->submsg_index];
upb_msg *submsg = upb_addmsg(frame, field, &subm); upb_msg *submsg = upb_addmsg(msg, field, subl, d);
CHK(submsg); CHK(submsg);
return upb_decode_msgfield(d, submsg, subm, len); return upb_decode_msgfield(ptr, subl, len, submsg, d);
} }
case UPB_DESCRIPTOR_TYPE_GROUP: case UPB_DESCRIPTOR_TYPE_GROUP:
return upb_append_unknown(d, frame); return upb_append_unknown(ptr, msg, d);
} }
#undef VARINT_CASE #undef VARINT_CASE
UPB_UNREACHABLE(); UPB_UNREACHABLE();
} }
static bool upb_decode_mapfield(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_mapfield(const char *ptr,
const upb_msglayout_field *field, int len) { const upb_msglayout *layout,
upb_map *map = *(upb_map**)&frame->msg[field->offset]; const upb_msglayout_field *field,
const upb_msglayout *entry = frame->layout->submsgs[field->submsg_index]; int len, upb_msg *msg, upb_decstate *d) {
upb_map *map = *PTR_AT(msg, field->offset, upb_map*);
const upb_msglayout *entry = layout->submsgs[field->submsg_index];
upb_map_entry ent; upb_map_entry ent;
if (!map) { if (!map) {
@ -504,51 +499,53 @@ static bool upb_decode_mapfield(upb_decstate *d, upb_decframe *frame,
UPB_ASSERT(val_field->number == 2); UPB_ASSERT(val_field->number == 2);
UPB_ASSERT(key_field->offset == 0); UPB_ASSERT(key_field->offset == 0);
UPB_ASSERT(val_field->offset == sizeof(upb_strview)); UPB_ASSERT(val_field->offset == sizeof(upb_strview));
map = _upb_map_new(frame->state->arena, key_size, val_size); map = _upb_map_new(d->arena, key_size, val_size);
*(upb_map**)&frame->msg[field->offset] = map; *PTR_AT(msg, field->offset, upb_map*) = map;
} }
/* Parse map entry. */ /* Parse map entry. */
memset(&ent, 0, sizeof(ent)); memset(&ent, 0, sizeof(ent));
CHK(upb_decode_msgfield(d, &ent.k, entry, len)); CHK(ptr = upb_decode_msgfield(ptr, entry, len, &ent.k, d));
/* Insert into map. */ /* Insert into map. */
_upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena); _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
return true; return ptr;
} }
static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame, static const char *upb_decode_delimitedfield(const char *ptr,
const upb_msglayout_field *field) { const upb_msglayout *layout,
const upb_msglayout_field *field,
upb_msg *msg, upb_decstate *d) {
int len; int len;
CHK(upb_decode_string(&d->ptr, d->limit, &len)); CHK(ptr = upb_decode_string(ptr, d->limit, &len));
if (field->label == UPB_LABEL_REPEATED) { if (field->label == UPB_LABEL_REPEATED) {
return upb_decode_toarray(d, frame, field, len); return upb_decode_toarray(ptr, layout, field, len, msg, d);
} else if (field->label == UPB_LABEL_MAP) { } else if (field->label == UPB_LABEL_MAP) {
return upb_decode_mapfield(d, frame, field, len); return upb_decode_mapfield(ptr, layout, field, len, msg, d);
} else { } else {
switch (field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: { case UPB_DESCRIPTOR_TYPE_BYTES: {
upb_strview str = upb_decode_strfield(d, len); upb_strview str;
CHK(upb_decode_addval(frame, field, &str, sizeof(str))); ptr = upb_decode_strfield(ptr, d, len, &str);
CHK(upb_decode_addval(msg, field, &str, sizeof(str), d));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_MESSAGE: { case UPB_DESCRIPTOR_TYPE_MESSAGE: {
const upb_msglayout *subm; const upb_msglayout *subl = layout->submsgs[field->submsg_index];
upb_msg *submsg = upb_getorcreatemsg(frame, field, &subm); upb_msg *submsg = upb_getorcreatemsg(msg, field, subl, d);
CHK(submsg); CHK(submsg);
CHK(upb_decode_msgfield(d, submsg, subm, len)); CHK(ptr = upb_decode_msgfield(ptr, subl, len, submsg, d));
break; break;
} }
default: default:
/* TODO(haberman): should we accept the last element of a packed? */ /* TODO(haberman): should we accept the last element of a packed? */
d->ptr += len; return upb_append_unknown(ptr + len, msg, d);
return upb_append_unknown(d, frame);
} }
upb_decode_setpresent(frame, field); upb_decode_setpresent(msg, field);
return true; return ptr;
} }
} }
@ -565,77 +562,75 @@ static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
return NULL; /* Unknown field. */ return NULL; /* Unknown field. */
} }
static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) { static const char *upb_decode_field(const char *ptr,
const upb_msglayout *layout, upb_msg *msg,
upb_decstate *d) {
uint32_t tag; uint32_t tag;
const upb_msglayout_field *field; const upb_msglayout_field *field;
int field_number; int field_number;
d->field_start = d->ptr; d->field_start = ptr;
CHK(upb_decode_varint32(&d->ptr, d->limit, &tag)); CHK(ptr = upb_decode_varint32(ptr, d->limit, &tag));
field_number = tag >> 3; field_number = tag >> 3;
field = upb_find_field(frame->layout, field_number); field = upb_find_field(layout, field_number);
if (field) { if (field) {
switch (tag & 7) { switch (tag & 7) {
case UPB_WIRE_TYPE_VARINT: case UPB_WIRE_TYPE_VARINT:
return upb_decode_varintfield(d, frame, field); return upb_decode_varintfield(ptr, msg, field, d);
case UPB_WIRE_TYPE_32BIT: case UPB_WIRE_TYPE_32BIT:
return upb_decode_32bitfield(d, frame, field); return upb_decode_32bitfield(ptr, field, msg, d);
case UPB_WIRE_TYPE_64BIT: case UPB_WIRE_TYPE_64BIT:
return upb_decode_64bitfield(d, frame, field); return upb_decode_64bitfield(ptr, field, msg, d);
case UPB_WIRE_TYPE_DELIMITED: case UPB_WIRE_TYPE_DELIMITED:
return upb_decode_delimitedfield(d, frame, field); return upb_decode_delimitedfield(ptr, layout, field, msg, d);
case UPB_WIRE_TYPE_START_GROUP: { case UPB_WIRE_TYPE_START_GROUP: {
const upb_msglayout *layout; const upb_msglayout *subl = layout->submsgs[field->submsg_index];
upb_msg *group; upb_msg *group;
if (field->label == UPB_LABEL_REPEATED) { if (field->label == UPB_LABEL_REPEATED) {
group = upb_addmsg(frame, field, &layout); group = upb_addmsg(msg, field, subl, d);
} else { } else {
group = upb_getorcreatemsg(frame, field, &layout); group = upb_getorcreatemsg(msg, field, subl, d);
} }
return upb_decode_groupfield(d, group, layout, field_number); return upb_decode_groupfield(ptr, subl, field_number, group, d);
} }
case UPB_WIRE_TYPE_END_GROUP: case UPB_WIRE_TYPE_END_GROUP:
d->end_group = field_number; d->end_group = field_number;
return true; return ptr;
default: default:
CHK(false); CHK(false);
} }
} else { } else {
CHK(field_number != 0); CHK(field_number != 0);
CHK(upb_skip_unknownfielddata(d, tag, -1)); CHK(ptr = upb_skip_unknownfielddata(ptr, d, tag, -1));
CHK(upb_append_unknown(d, frame)); CHK(ptr = upb_append_unknown(ptr, msg, d));
return true; return ptr;
} }
UPB_UNREACHABLE(); UPB_UNREACHABLE();
} }
static bool upb_decode_message(upb_decstate *d, char *msg, const upb_msglayout *l) { static const char *upb_decode_message(const char *ptr, const upb_msglayout *l,
upb_decframe frame; upb_msg *msg, upb_decstate *d) {
frame.msg = msg; while (ptr < d->limit) {
frame.layout = l; CHK(ptr = upb_decode_field(ptr, l, msg, d));
frame.state = d;
while (d->ptr < d->limit) {
CHK(upb_decode_field(d, &frame));
} }
return true; return ptr;
} }
bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
upb_arena *arena) { upb_arena *arena) {
upb_decstate state; upb_decstate state;
state.ptr = buf;
state.limit = buf + size; state.limit = buf + size;
state.arena = arena; state.arena = arena;
state.depth = 64; state.depth = 64;
state.end_group = 0; state.end_group = 0;
CHK(upb_decode_message(&state, msg, l)); CHK(upb_decode_message(buf, l, msg, &state));
return state.end_group == 0; return state.end_group == 0;
} }
#undef CHK #undef CHK
#undef PTR_AT

@ -1331,7 +1331,7 @@ static bool create_fielddef(
break; break;
} }
} }
assert(found); UPB_ASSERT(found);
} }
} else { } else {
/* extension field. */ /* extension field. */

@ -389,7 +389,7 @@ static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
upb_handlertype_t type) { upb_handlertype_t type) {
upb_selector_t sel; upb_selector_t sel;
bool ok = upb_handlers_getselector(p->top->f, type, &sel); bool ok = upb_handlers_getselector(p->top->f, type, &sel);
UPB_ASSERT(ok); UPB_ASSUME(ok);
return sel; return sel;
} }
@ -414,7 +414,7 @@ static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
const upb_json_parsermethod *method; const upb_json_parsermethod *method;
ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
UPB_ASSERT(ok); UPB_ASSUME(ok);
method = upb_value_getconstptr(v); method = upb_value_getconstptr(v);
frame->name_table = &method->name_table; frame->name_table = &method->name_table;
@ -2019,7 +2019,7 @@ static void end_member(upb_json_parser *p) {
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */ /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
p->top--; p->top--;
ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel); ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
UPB_ASSERT(ok); UPB_ASSUME(ok);
upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel); upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
} }

@ -910,10 +910,10 @@ const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
} else { } else {
g = mgroup_new(h, c->lazy); g = mgroup_new(h, c->lazy);
ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g)); ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g));
UPB_ASSERT(ok); UPB_ASSUME(ok);
} }
ok = upb_inttable_lookupptr(&g->methods, h, &v); ok = upb_inttable_lookupptr(&g->methods, h, &v);
UPB_ASSERT(ok); UPB_ASSUME(ok);
return upb_value_getptr(v); return upb_value_getptr(v);
} }

@ -128,6 +128,18 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
#define UPB_UNUSED(var) (void)var #define UPB_UNUSED(var) (void)var
/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
*/
#ifdef NDEBUG
#ifdef __GNUC__
#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
#else
#define UPB_ASSUME(expr) do {} if (false && (expr))
#endif
#else
#define UPB_ASSUME(expr) assert(expr)
#endif
/* UPB_ASSERT(): in release mode, we use the expression without letting it be /* UPB_ASSERT(): in release mode, we use the expression without letting it be
* evaluated. This prevents "unused variable" warnings. */ * evaluated. This prevents "unused variable" warnings. */
#ifdef NDEBUG #ifdef NDEBUG

@ -12,6 +12,7 @@
#undef UPB_MAX #undef UPB_MAX
#undef UPB_MIN #undef UPB_MIN
#undef UPB_UNUSED #undef UPB_UNUSED
#undef UPB_ASSUME
#undef UPB_ASSERT #undef UPB_ASSERT
#undef UPB_ASSERT_DEBUGVAR #undef UPB_ASSERT_DEBUGVAR
#undef UPB_UNREACHABLE #undef UPB_UNREACHABLE

Loading…
Cancel
Save