FORCEINLINE uint64_t upb_decode_varint(upb_decoder *d) { if (upb_decoder_bufleft(d) >= 10) { // Fast case. upb_decoderet r = upb_vdecode_fast(d->ptr); if (r.p == NULL) upb_decoder_abortjmp(d, "Unterminated varint"); upb_decoder_advance(d, r.p - d->ptr); return r.val; } else if (upb_decoder_bufleft(d) > 0) { // Intermediate case -- worth it? char tmpbuf[10]; memset(tmpbuf, 0x80, 10); memcpy(tmpbuf, d->ptr, upb_decoder_bufleft(d)); upb_decoderet r = upb_vdecode_fast(tmpbuf); if (r.p != NULL) { upb_decoder_advance(d, r.p - tmpbuf); return r.val; } } // Slow case -- varint spans buffer seam. return upb_decode_varint_slow(d); }
// Decodes a varint from the current buffer position. // Returns a status code as described in decoder.int.h. FORCEINLINE int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) { *u64 = *d->ptr; advance(d, 1); return DECODE_OK; } else if (curbufleft(d) >= 10) { // Fast case. upb_decoderet r = upb_vdecode_fast(d->ptr); if (r.p == NULL) { seterr(d, kUnterminatedVarint); return upb_pbdecoder_suspend(d); } advance(d, r.p - d->ptr); *u64 = r.val; return DECODE_OK; } else { // Slow case -- varint spans buffer seam. return upb_pbdecoder_decode_varint_slow(d, u64); } }