43 #include "upb/port_def.inc"
49 #define UPB_PARSE_PARAMS \
50 upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \
51 uint64_t hasbits, uint64_t data
53 #define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
55 #define RETURN_GENERIC(m) \
59 return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
77 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
83 int overrun =
ptr -
d->end;
93 UPB_MUSTTAIL return fastdecode_isdonefallback(UPB_PARSE_ARGS);
99 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
103 static bool fastdecode_checktag(
uint16_t data,
int tagbytes) {
105 return (
data & 0xff) == 0;
112 static const char* fastdecode_longsize(
const char*
ptr,
int*
size) {
116 for (
i = 0;
i < 3;
i++) {
119 *
size += (
byte - 1) << (7 + 7 *
i);
127 *
size += (
byte - 1) << 28;
132 static bool fastdecode_boundscheck(
const char*
ptr,
size_t len,
137 return res < uptr || res > uend;
141 static bool fastdecode_boundscheck2(
const char*
ptr,
size_t len,
151 return res < uptr || res > uend;
154 typedef const char* fastdecode_delimfunc(
upb_Decoder*
d,
const char*
ptr,
158 static const char* fastdecode_delimited(
upb_Decoder*
d,
const char*
ptr,
159 fastdecode_delimfunc*
func,
void*
ctx) {
162 if (fastdecode_boundscheck2(
ptr,
len,
d->limit_ptr)) {
174 if (
ptr -
d->end + (
int)
len >
d->limit) {
184 const char* saved_limit_ptr =
d->limit_ptr;
185 int saved_limit =
d->limit;
187 d->limit =
d->limit_ptr -
d->end;
190 d->limit_ptr = saved_limit_ptr;
191 d->limit = saved_limit;
212 fastdecode_next
next;
214 } fastdecode_nextret;
218 fastdecode_arr* farr,
int valbytes) {
221 size_t old_bytes =
old_size * valbytes;
223 size_t new_bytes =
new_size * valbytes;
226 uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
230 farr->end = (
void*)(new_ptr + (
new_size * valbytes));
245 static void fastdecode_commitarr(
void*
dst, fastdecode_arr* farr,
252 static fastdecode_nextret fastdecode_nextrepeated(
upb_Decoder*
d,
void*
dst,
254 fastdecode_arr* farr,
257 fastdecode_nextret
ret;
258 dst = (
char*)
dst + valbytes;
262 if (fastdecode_tagmatch(
ret.tag,
data, tagbytes)) {
263 ret.next = FD_NEXT_SAMEFIELD;
265 fastdecode_commitarr(
dst, farr, valbytes);
266 ret.next = FD_NEXT_OTHERFIELD;
269 fastdecode_commitarr(
dst, farr, valbytes);
270 ret.next = FD_NEXT_ATLIMIT;
279 size_t ofs =
data >> 48;
280 return (
char*)
msg + ofs;
286 uint64_t* hasbits, fastdecode_arr* farr,
287 int valbytes, upb_card card) {
292 *hasbits |= 1ull << hasbit_index;
293 return fastdecode_fieldmem(
msg, *
data);
299 *oneof_case = field_number;
300 return fastdecode_fieldmem(
msg, *
data);
304 uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
316 farr->end =
begin + (farr->arr->size * valbytes);
318 return begin + (farr->arr->len * valbytes);
326 static bool fastdecode_flippacked(
uint64_t*
data,
int tagbytes) {
327 *
data ^= (0x2 ^ 0x0);
328 return fastdecode_checktag(*
data, tagbytes);
331 #define FASTDECODE_CHECKPACKED(tagbytes, card, func) \
332 if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
333 if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { \
334 UPB_MUSTTAIL return func(UPB_PARSE_ARGS); \
336 RETURN_GENERIC("packed check tag mismatch\n"); \
349 }
else if (valbytes == 8) {
350 return (val >> 1) ^ -(
int64_t)(val & 1);
358 static const char* fastdecode_varint64(
const char*
ptr,
uint64_t* val) {
363 for (
i = 0;
i < 8;
i++) {
366 *val += (
byte - 1) << (7 + 7 *
i);
374 *val += (
byte - 1) << 63;
381 #define FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
382 valbytes, card, zigzag, packed) \
385 fastdecode_arr farr; \
387 FASTDECODE_CHECKPACKED(tagbytes, card, packed); \
389 dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
391 if (card == CARD_r) { \
392 if (UPB_UNLIKELY(!dst)) { \
393 RETURN_GENERIC("need array resize\n"); \
398 if (card == CARD_r) { \
399 dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
403 ptr = fastdecode_varint64(ptr, &val); \
404 if (ptr == NULL) return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
405 val = fastdecode_munge(val, valbytes, zigzag); \
406 memcpy(dst, &val, valbytes); \
408 if (card == CARD_r) { \
409 fastdecode_nextret ret = fastdecode_nextrepeated( \
410 d, dst, &ptr, &farr, data, tagbytes, valbytes); \
411 switch (ret.next) { \
412 case FD_NEXT_SAMEFIELD: \
415 case FD_NEXT_OTHERFIELD: \
417 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
418 case FD_NEXT_ATLIMIT: \
423 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
430 } fastdecode_varintdata;
433 static const char* fastdecode_topackedvarint(
upb_Decoder*
d,
const char*
ptr,
435 fastdecode_varintdata*
data =
ctx;
441 ptr = fastdecode_varint64(
ptr, &val);
442 if (
ptr == NULL)
return NULL;
443 val = fastdecode_munge(val,
data->valbytes,
data->zigzag);
448 fastdecode_commitarr(
dst, &
data->farr,
data->valbytes);
452 #define FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
453 valbytes, zigzag, unpacked) \
454 fastdecode_varintdata ctx = {valbytes, zigzag}; \
456 FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked); \
458 ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, \
460 if (UPB_UNLIKELY(!ctx.dst)) { \
461 RETURN_GENERIC("need array resize\n"); \
465 ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); \
467 if (UPB_UNLIKELY(ptr == NULL)) { \
468 return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
471 UPB_MUSTTAIL return fastdecode_dispatch(d, ptr, msg, table, hasbits, 0);
473 #define FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
474 valbytes, card, zigzag, unpacked, packed) \
475 if (card == CARD_p) { \
476 FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
477 valbytes, zigzag, unpacked); \
479 FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
480 valbytes, card, zigzag, packed); \
490 #define F(card, type, valbytes, tagbytes) \
492 const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
493 FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
494 CARD_##card, type##_ZZ, \
495 upb_pr##type##valbytes##_##tagbytes##bt, \
496 upb_pp##type##valbytes##_##tagbytes##bt); \
499 #define TYPES(card, tagbytes) \
500 F(card, b, 1, tagbytes) \
501 F(card, v, 4, tagbytes) \
502 F(card, v, 8, tagbytes) \
503 F(card, z, 4, tagbytes) \
504 F(card, z, 8, tagbytes)
506 #define TAGBYTES(card) \
524 #undef FASTDECODE_UNPACKEDVARINT
525 #undef FASTDECODE_PACKEDVARINT
526 #undef FASTDECODE_VARINT
530 #define FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
531 valbytes, card, packed) \
533 fastdecode_arr farr; \
535 FASTDECODE_CHECKPACKED(tagbytes, card, packed) \
537 dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
539 if (card == CARD_r) { \
540 if (UPB_UNLIKELY(!dst)) { \
541 RETURN_GENERIC("couldn't allocate array in arena\n"); \
546 if (card == CARD_r) { \
547 dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
551 memcpy(dst, ptr, valbytes); \
554 if (card == CARD_r) { \
555 fastdecode_nextret ret = fastdecode_nextrepeated( \
556 d, dst, &ptr, &farr, data, tagbytes, valbytes); \
557 switch (ret.next) { \
558 case FD_NEXT_SAMEFIELD: \
561 case FD_NEXT_OTHERFIELD: \
563 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
564 case FD_NEXT_ATLIMIT: \
569 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
571 #define FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
572 valbytes, unpacked) \
573 FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked) \
576 int size = (uint8_t)ptr[0]; \
579 ptr = fastdecode_longsize(ptr, &size); \
582 if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr) || \
583 (size % valbytes) != 0)) { \
584 return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
587 upb_Array** arr_p = fastdecode_fieldmem(msg, data); \
588 upb_Array* arr = *arr_p; \
589 uint8_t elem_size_lg2 = __builtin_ctz(valbytes); \
590 int elems = size / valbytes; \
592 if (UPB_LIKELY(!arr)) { \
593 *arr_p = arr = _upb_Array_New(&d->arena, elems, elem_size_lg2); \
595 return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
598 _upb_Array_Resize(arr, elems, &d->arena); \
601 char* dst = _upb_array_ptr(arr); \
602 memcpy(dst, ptr, size); \
606 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
608 #define FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
609 valbytes, card, unpacked, packed) \
610 if (card == CARD_p) { \
611 FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
612 valbytes, unpacked); \
614 FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
615 valbytes, card, packed); \
621 #define F(card, valbytes, tagbytes) \
623 const char* upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
624 FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
625 CARD_##card, upb_ppf##valbytes##_##tagbytes##bt, \
626 upb_prf##valbytes##_##tagbytes##bt); \
629 #define TYPES(card, tagbytes) \
630 F(card, 4, tagbytes) \
633 #define TAGBYTES(card) \
645 #undef FASTDECODE_UNPACKEDFIXED
646 #undef FASTDECODE_PACKEDFIXED
650 typedef const char* fastdecode_copystr_func(
struct upb_Decoder*
d,
657 static const char* fastdecode_verifyutf8(
upb_Decoder*
d,
const char*
ptr,
664 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
667 #define FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, validate_utf8) \
668 int size = (uint8_t)ptr[0]; \
671 ptr = fastdecode_longsize(ptr, &size); \
674 if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { \
676 return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
679 if (d->options & kUpb_DecodeOption_AliasString) { \
683 char* data = upb_Arena_Malloc(&d->arena, size); \
685 return fastdecode_err(d, kUpb_DecodeStatus_OutOfMemory); \
687 memcpy(data, ptr, size); \
693 if (validate_utf8) { \
694 data = (uint64_t)dst; \
695 UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
697 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
701 static const char* fastdecode_longstring_utf8(
struct upb_Decoder*
d,
710 static const char* fastdecode_longstring_noutf8(
720 d->arena.head.ptr +=
copy;
727 #define FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
728 card, validate_utf8) \
729 upb_StringView* dst; \
730 fastdecode_arr farr; \
736 UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0); \
737 UPB_ASSERT(fastdecode_checktag(data, tagbytes)); \
739 dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
740 sizeof(upb_StringView), card); \
743 if (card == CARD_r) { \
744 dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView)); \
747 size = (uint8_t)ptr[tagbytes]; \
748 ptr += tagbytes + 1; \
751 buf = d->arena.head.ptr; \
752 arena_has = _upb_ArenaHas(&d->arena); \
753 common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); \
755 if (UPB_LIKELY(size <= 15 - tagbytes)) { \
756 if (arena_has < 16) goto longstr; \
757 d->arena.head.ptr += 16; \
758 memcpy(buf, ptr - tagbytes - 1, 16); \
759 dst->data = buf + tagbytes + 1; \
760 } else if (UPB_LIKELY(size <= 32)) { \
761 if (UPB_UNLIKELY(common_has < 32)) goto longstr; \
762 fastdecode_docopy(d, ptr, size, 32, buf, dst); \
763 } else if (UPB_LIKELY(size <= 64)) { \
764 if (UPB_UNLIKELY(common_has < 64)) goto longstr; \
765 fastdecode_docopy(d, ptr, size, 64, buf, dst); \
766 } else if (UPB_LIKELY(size < 128)) { \
767 if (UPB_UNLIKELY(common_has < 128)) goto longstr; \
768 fastdecode_docopy(d, ptr, size, 128, buf, dst); \
775 if (card == CARD_r) { \
776 if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
777 return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8); \
779 fastdecode_nextret ret = fastdecode_nextrepeated( \
780 d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView)); \
781 switch (ret.next) { \
782 case FD_NEXT_SAMEFIELD: \
785 case FD_NEXT_OTHERFIELD: \
787 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
788 case FD_NEXT_ATLIMIT: \
793 if (card != CARD_r && validate_utf8) { \
794 data = (uint64_t)dst; \
795 UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
798 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
801 if (card == CARD_r) { \
802 fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView)); \
805 if (validate_utf8) { \
806 UPB_MUSTTAIL return fastdecode_longstring_utf8(d, ptr, msg, table, \
807 hasbits, (uint64_t)dst); \
809 UPB_MUSTTAIL return fastdecode_longstring_noutf8(d, ptr, msg, table, \
810 hasbits, (uint64_t)dst); \
813 #define FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, card, \
814 copyfunc, validate_utf8) \
815 upb_StringView* dst; \
816 fastdecode_arr farr; \
819 if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
820 RETURN_GENERIC("string field tag mismatch\n"); \
823 if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
824 UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS); \
827 dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
828 sizeof(upb_StringView), card); \
831 if (card == CARD_r) { \
832 dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView)); \
835 size = (int8_t)ptr[tagbytes]; \
836 ptr += tagbytes + 1; \
840 if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { \
842 if (validate_utf8) { \
843 return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, \
846 return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, \
853 if (card == CARD_r) { \
854 if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
855 return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8); \
857 fastdecode_nextret ret = fastdecode_nextrepeated( \
858 d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView)); \
859 switch (ret.next) { \
860 case FD_NEXT_SAMEFIELD: \
862 if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
866 fastdecode_commitarr(dst, &farr, sizeof(upb_StringView)); \
868 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
871 case FD_NEXT_OTHERFIELD: \
873 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
874 case FD_NEXT_ATLIMIT: \
879 if (card != CARD_r && validate_utf8) { \
880 data = (uint64_t)dst; \
881 UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
884 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
889 #define s_VALIDATE true
890 #define b_VALIDATE false
892 #define F(card, tagbytes, type) \
894 const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
895 FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
896 CARD_##card, type##_VALIDATE); \
898 const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
899 FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, \
900 CARD_##card, upb_c##card##type##_##tagbytes##bt, \
904 #define UTF8(card, tagbytes) \
905 F(card, tagbytes, s) \
908 #define TAGBYTES(card) \
920 #undef FASTDECODE_LONGSTRING
921 #undef FASTDECODE_COPYSTRING
922 #undef FASTDECODE_STRING
928 int msg_ceil_bytes) {
934 msg_data =
d->arena.head.ptr;
935 d->arena.head.ptr +=
size;
937 memset(msg_data, 0, msg_ceil_bytes);
949 } fastdecode_submsgdata;
952 static const char* fastdecode_tosubmsg(
upb_Decoder*
d,
const char*
ptr,
954 fastdecode_submsgdata* submsg =
ctx;
955 ptr = fastdecode_dispatch(
d,
ptr, submsg->msg, submsg->table, 0, 0);
960 #define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \
961 msg_ceil_bytes, card) \
963 if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
964 RETURN_GENERIC("submessage field tag mismatch\n"); \
967 if (--d->depth == 0) { \
968 return fastdecode_err(d, kUpb_DecodeStatus_MaxDepthExceeded); \
972 uint32_t submsg_idx = (data >> 16) & 0xff; \
973 const upb_MiniTable* tablep = decode_totablep(table); \
974 const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg; \
975 fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \
976 fastdecode_arr farr; \
978 if (subtablep->table_mask == (uint8_t)-1) { \
979 RETURN_GENERIC("submessage doesn't have fast tables."); \
982 dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
983 sizeof(upb_Message*), card); \
985 if (card == CARD_s) { \
986 *(uint32_t*)msg |= hasbits; \
991 if (card == CARD_r) { \
992 dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \
997 if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \
998 *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \
1002 ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \
1004 if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \
1005 return fastdecode_err(d, kUpb_DecodeStatus_Malformed); \
1008 if (card == CARD_r) { \
1009 fastdecode_nextret ret = fastdecode_nextrepeated( \
1010 d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \
1011 switch (ret.next) { \
1012 case FD_NEXT_SAMEFIELD: \
1015 case FD_NEXT_OTHERFIELD: \
1018 UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
1019 case FD_NEXT_ATLIMIT: \
1026 UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
1028 #define F(card, tagbytes, size_ceil, ceil_arg) \
1029 const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \
1030 UPB_PARSE_PARAMS) { \
1031 FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \
1035 #define SIZES(card, tagbytes) \
1036 F(card, tagbytes, 64, 64) \
1037 F(card, tagbytes, 128, 128) \
1038 F(card, tagbytes, 192, 192) \
1039 F(card, tagbytes, 256, 256) \
1040 F(card, tagbytes, max, -1)
1042 #define TAGBYTES(card) \
1053 #undef FASTDECODE_SUBMSG