From 4bcdea25f03e529223ed8ae080bdf5aba71d816d Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Fri, 31 Jul 2009 16:35:24 -0700 Subject: More work on serialization. --- src/upb_serialize.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'src') diff --git a/src/upb_serialize.h b/src/upb_serialize.h index de5e57d..b785e0e 100644 --- a/src/upb_serialize.h +++ b/src/upb_serialize.h @@ -51,13 +51,24 @@ INLINE upb_status_t upb_put_v_uint32_t(uint8_t *buf, uint8_t *end, return UPB_STATUS_OK; } +INLINE void upb_put32(uint8_t *buf, uint32_t val) { + buf[0] = val & 0xff; + buf[1] = (val >> 8) & 0xff; + buf[2] = (val >> 16) & 0xff; + buf[3] = (val >> 24); +} + /* Puts a fixed-length 32-bit integer (wire type: UPB_WIRE_TYPE_32BIT). */ INLINE upb_status_t upb_put_f_uint32_t(uint8_t *buf, uint8_t *end, uint32_t val, uint8_t **outbuf) { uint8_t *uint32_end = buf + sizeof(uint32_t); if(uint32_end > end) return UPB_STATUS_NEED_MORE_DATA; +#if UPB_UNALIGNED_READS_OK *(uint32_t*)buf = val; +#else + upb_put32(buf, val); +#endif *outbuf = uint32_end; return UPB_STATUS_OK; } @@ -68,11 +79,43 @@ INLINE upb_status_t upb_put_f_uint64_t(uint8_t *buf, uint8_t *end, { uint8_t *uint64_end = buf + sizeof(uint64_t); if(uint64_end > end) return UPB_STATUS_NEED_MORE_DATA; +#if UPB_UNALIGNED_READS_OK *(uint64_t*)buf = val; +#else + upb_put32(buf, (uint32_t)val); + upb_put32(buf, (uint32_t)(val >> 32)); +#endif *outbuf = uint64_end; return UPB_STATUS_OK; } +INLINE size_t upb_v_uint64_t_size(uint64_t val) { +#ifdef __GNUC__ + int high_bit = 63 - __builtin_clzll(val); /* 0-based, undef if val == 0. */ +#else + int high_bit = 0; + uint64_t tmp = val; + while(tmp >>= 1) high_bit++; +#endif + return val == 0 ? 1 : high_bit / 7 + 1; +} + +INLINE size_t upb_v_int32_t_size(int32_t val) { + /* v_uint32's are sign-extended to maintain wire compatibility with int64s. */ + return upb_v_uint64_t_size((int64_t)val); +} +INLINE size_t upb_v_uint32_t_size(uint32_t val) { + return upb_v_uint64_t_size(val); +} +INLINE size_t upb_f_uint64_t_size(uint64_t val) { + (void)val; /* Length is independent of value. */ + return sizeof(uint64_t); +} +INLINE size_t upb_f_uint32_t_size(uint32_t val) { + (void)val; /* Length is independent of value. */ + return sizeof(uint32_t); +} + /* Functions to write .proto values. ******************************************/ /* Performs zig-zag encoding, which is used by sint32 and sint64. */ @@ -88,6 +131,9 @@ INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } * upb_status_t upb_put_INT32(uint8_t *buf, uint8_t *end, int32_t val, * uint8_t **outbuf); * + * // Returns the number of bytes required to serialize val. + * size_t upb_get_INT32_size(int32_t val); + * * // Given a .proto value s (source) convert it to a wire value. * uint32_t upb_vtowv_INT32(int32_t s); */ @@ -104,6 +150,9 @@ INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } } #define T(type, v_or_f, wire_t, val_t, member_name) \ + INLINE size_t upb_get_ ## type ## _size(val_t val) { \ + return upb_ ## v_or_f ## _ ## wire_t ## _size(val); \ + } \ VTOWV(type, wire_t, val_t); /* prototype for PUT below */ \ PUT(type, v_or_f, wire_t, val_t, member_name) \ VTOWV(type, wire_t, val_t) @@ -134,6 +183,10 @@ T(FLOAT, f, uint32_t, float, _float) { #undef PUT #undef T +/* Functions to get sizes of serialized values without serializing. ***********/ + + + #ifdef __cplusplus } /* extern "C" */ #endif -- cgit v1.2.3