summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-07-31 16:35:24 -0700
committerJoshua Haberman <joshua@reverberate.org>2009-07-31 16:35:24 -0700
commit4bcdea25f03e529223ed8ae080bdf5aba71d816d (patch)
tree9845199db307e4c5d06109d17f917a3ac41b88e8 /src
parent4240e0e5989fadd367c29651e0a0b01d499927b0 (diff)
More work on serialization.
Diffstat (limited to 'src')
-rw-r--r--src/upb_serialize.h53
1 files changed, 53 insertions, 0 deletions
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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback