diff --git a/upb/decode_fast.c b/upb/decode_fast.c index c8961d77eb..e77e85947e 100644 --- a/upb/decode_fast.c +++ b/upb/decode_fast.c @@ -19,9 +19,9 @@ #define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data -#define RETURN_GENERIC(msg) \ - /* fprintf(stderr, msg); */ \ - return fastdecode_generic(UPB_PARSE_ARGS); +#define RETURN_GENERIC(m) \ + /* fprintf(stderr, m); */ \ + return fastdecode_generic(d, ptr, msg, table, hasbits, 0); typedef enum { CARD_s = 0, /* Singular (optional, non-repeated) */ @@ -264,26 +264,37 @@ static bool fastdecode_boundscheck(const char *ptr, size_t len, return res < uptr || res > uend; } -UPB_NOINLINE +typedef const char *fastdecode_copystr_func(struct upb_decstate *d, + const char *ptr, upb_msg *msg, + const upb_msglayout *table, + uint64_t hasbits, upb_strview *dst); + +UPB_FORCEINLINE static const char *fastdecode_copystring(struct upb_decstate *d, - size_t len, upb_msg *msg, + const char *ptr, upb_msg *msg, const upb_msglayout *table, - uint64_t hasbits, upb_strview *str) { - char *ptr = (char*)str->data; + uint64_t hasbits, upb_strview *dst, + int tagbytes) { + int64_t len = (int8_t)*ptr; + ptr++; + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, len, d->limit_ptr))) { + ptr -= tagbytes + 1; + RETURN_GENERIC("string field len >1 byte\n"); + } char *data = upb_arena_malloc(&d->arena, len); if (!data) { return fastdecode_err(d); } memcpy(data, ptr, len); - str->data = data; + dst->data = data; + dst->size = len; return fastdecode_dispatch(d, ptr + len, msg, table, hasbits); } UPB_FORCEINLINE static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes, - upb_card card) { + upb_card card, fastdecode_copystr_func *func) { upb_strview *dst; - const char *str; int64_t len; if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { RETURN_GENERIC("string field tag mismatch\n"); @@ -291,34 +302,51 @@ static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes, dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, sizeof(upb_strview), card); + if (UPB_UNLIKELY(!d->alias)) { + return func(d, ptr + tagbytes, msg, table, hasbits, dst); + } + + len = (int8_t)ptr[tagbytes]; - str = ptr + tagbytes + 1; - dst->data = str; + ptr += tagbytes + 1; + dst->data = ptr; dst->size = len; - if (UPB_UNLIKELY(fastdecode_boundscheck(str, len, d->limit_ptr))) { + if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, len, d->limit_ptr))) { dst->size = 0; + ptr -= tagbytes + 1; RETURN_GENERIC("string field len >1 byte\n"); } - if (!d->alias) { - return fastdecode_copystring(d, len, msg, table, hasbits, dst); - } - return fastdecode_dispatch(d, str + len, msg, table, hasbits); + return fastdecode_dispatch(d, ptr + len, msg, table, hasbits); +} + +UPB_NOINLINE +static const char *upb_copystr_1bt(upb_decstate *d, const char *ptr, + upb_msg *msg, const upb_msglayout *table, + uint64_t hasbits, upb_strview *dst) { + return fastdecode_copystring(d, ptr, msg, table, hasbits, dst, 1); +} + +UPB_NOINLINE +static const char *upb_copystr_2bt(upb_decstate *d, const char *ptr, upb_msg *msg, + const upb_msglayout *table, uint64_t hasbits, + upb_strview *dst) { + return fastdecode_copystring(d, ptr, msg, table, hasbits, dst, 2); } const char *upb_pss_1bt(UPB_PARSE_PARAMS) { - return fastdecode_string(UPB_PARSE_ARGS, 1, CARD_s); + return fastdecode_string(UPB_PARSE_ARGS, 1, CARD_s, &upb_copystr_1bt); } const char *upb_pos_1bt(UPB_PARSE_PARAMS) { - return fastdecode_string(UPB_PARSE_ARGS, 1, CARD_o); + return fastdecode_string(UPB_PARSE_ARGS, 1, CARD_o, &upb_copystr_1bt); } const char *upb_pss_2bt(UPB_PARSE_PARAMS) { - return fastdecode_string(UPB_PARSE_ARGS, 2, CARD_s); + return fastdecode_string(UPB_PARSE_ARGS, 2, CARD_s, &upb_copystr_2bt); } const char *upb_pos_2bt(UPB_PARSE_PARAMS) { - return fastdecode_string(UPB_PARSE_ARGS, 2, CARD_o); + return fastdecode_string(UPB_PARSE_ARGS, 2, CARD_o, &upb_copystr_2bt); } /* message fields *************************************************************/