Don't store field_start, derive it separately.

pull/13171/head
Joshua Haberman 4 years ago
parent e4855feec8
commit dfa28861cc
  1. 45
      upb/decode.c

@ -421,7 +421,6 @@ static const char *decode_enum_toarray(upb_decstate *d, const char *ptr,
return ptr; return ptr;
} }
#include <stdio.h>
UPB_FORCEINLINE UPB_FORCEINLINE
static const char *decode_fixed_packed(upb_decstate *d, const char *ptr, static const char *decode_fixed_packed(upb_decstate *d, const char *ptr,
upb_array *arr, wireval *val, upb_array *arr, wireval *val,
@ -844,23 +843,51 @@ static const char *decode_known(upb_decstate *d, const char *ptr, upb_msg *msg,
} }
} }
UPB_FORCEINLINE static const char *decode_reverse_skip_varint(const char *ptr, uint64_t val) {
uint64_t seen = 0;
do {
ptr--;
seen <<= 7;
seen |= *ptr & 0x7f;
} while (seen != val);
return ptr;
}
static const char *decode_unknown(upb_decstate *d, const char *ptr, static const char *decode_unknown(upb_decstate *d, const char *ptr,
upb_msg *msg, int field_number, int wire_type, upb_msg *msg, int field_number, int wire_type,
wireval val, const char **field_start) { wireval val) {
if (field_number == 0) return decode_err(d); if (field_number == 0) return decode_err(d);
if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size; if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
if (msg) { if (msg) {
const char *start = ptr;
switch (wire_type) {
case UPB_WIRE_TYPE_VARINT:
case UPB_WIRE_TYPE_DELIMITED:
start--;
while (start[-1] & 0x80) start--;
break;
case UPB_WIRE_TYPE_32BIT:
start -= 4;
break;
case UPB_WIRE_TYPE_64BIT:
start -= 8;
break;
default:
break;
}
start = decode_reverse_skip_varint(start, (field_number << 3) | wire_type);
if (wire_type == UPB_WIRE_TYPE_START_GROUP) { if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
d->unknown = *field_start; d->unknown = start;
d->unknown_msg = msg; d->unknown_msg = msg;
ptr = decode_group(d, ptr, NULL, NULL, field_number); ptr = decode_group(d, ptr, NULL, NULL, field_number);
d->unknown_msg = NULL; d->unknown_msg = NULL;
*field_start = d->unknown; d->unknown = NULL;
} }
if (!_upb_msg_addunknown(msg, *field_start, ptr - *field_start, if (!_upb_msg_addunknown(msg, start, ptr - start, &d->arena)) {
&d->arena)) {
return decode_err(d); return decode_err(d);
} }
} else if (wire_type == UPB_WIRE_TYPE_START_GROUP) { } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
@ -878,7 +905,6 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout_field *field; const upb_msglayout_field *field;
int field_number; int field_number;
int wire_type; int wire_type;
const char *field_start = ptr;
wireval val; wireval val;
int op; int op;
@ -900,8 +926,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
} else { } else {
switch (op) { switch (op) {
case OP_UNKNOWN: case OP_UNKNOWN:
ptr = decode_unknown(d, ptr, msg, field_number, wire_type, val, ptr = decode_unknown(d, ptr, msg, field_number, wire_type, val);
&field_start);
break; break;
case OP_MSGSET_ITEM: case OP_MSGSET_ITEM:
ptr = decode_msgset(d, ptr, msg, layout); ptr = decode_msgset(d, ptr, msg, layout);

Loading…
Cancel
Save