// Call to indicate the end of a delimited region. We now know the length of // the delimited region. If we are not nested inside any other delimited // regions, we can now emit all of the buffered data we accumulated. static bool end_delim(upb_pb_encoder *e) { accumulate(e); size_t msglen = top(e)->msglen; if (e->top == e->stack) { // All lengths are now available, emit all buffered data. char buf[UPB_PB_VARINT_MAX_LEN]; upb_pb_encoder_segment *s; const char *ptr = e->buf; for (s = e->segbuf; s <= e->segptr; s++) { size_t lenbytes = upb_vencode64(s->msglen, buf); putbuf(e, buf, lenbytes); putbuf(e, ptr, s->seglen); ptr += s->seglen; } e->ptr = e->buf; e->top = NULL; } else { // Need to keep buffering; propagate length info into enclosing submessages. --e->top; top(e)->msglen += msglen + upb_varint_size(msglen); } return true; }
/* Test that we can round-trip from int->varint->int. */ static void test_varint_for_num(upb_decoderet (*decoder)(const char*), uint64_t num) { char buf[16]; size_t bytes; upb_decoderet r; memset(buf, 0xff, sizeof(buf)); bytes = upb_vencode64(num, buf); if (num <= UINT32_MAX) { uint64_t encoded = upb_vencode32(num); char buf2[16]; upb_decoderet r; memset(buf2, 0, sizeof(buf2)); memcpy(&buf2, &encoded, 8); r = decoder(buf2); ASSERT(r.val == num); ASSERT(r.p == buf2 + upb_value_size(encoded)); ASSERT(upb_zzenc_32(upb_zzdec_32(num)) == num); } r = decoder(buf); ASSERT(r.val == num); ASSERT(r.p == buf + bytes); ASSERT(upb_zzenc_64(upb_zzdec_64(num)) == num); }
static bool encode_varint(upb_pb_encoder *e, uint64_t val) { if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) { return false; } encoder_advance(e, upb_vencode64(val, e->ptr)); return true; }
// Allocates a new tag for this field, and sets it in these handlerattr. static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt, upb_handlerattr *attr) { uint32_t n = upb_fielddef_number(f); tag_t *tag = malloc(sizeof(tag_t)); tag->bytes = upb_vencode64((n << 3) | wt, tag->tag); upb_handlerattr_init(attr); upb_handlerattr_sethandlerdata(attr, tag); upb_handlers_addcleanup(h, tag, free); }