|
|
@ -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 |
|
|
|