From cd3d737d5e14937fb88b80979ab4743a5c3e7fb6 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 29 Jul 2009 13:00:16 -0700 Subject: Add sketch of deserializing code. --- src/upb_inlinedefs.c | 4 ++ src/upb_parse.h | 4 +- src/upb_serialize.h | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 src/upb_serialize.h (limited to 'src') diff --git a/src/upb_inlinedefs.c b/src/upb_inlinedefs.c index 60863c4..dae5c01 100644 --- a/src/upb_inlinedefs.c +++ b/src/upb_inlinedefs.c @@ -12,8 +12,12 @@ */ #define INLINE +#include "upb_array.h" #include "upb_context.h" #include "upb_enum.h" #include "upb_msg.h" #include "upb_parse.h" +#include "upb_serialize.h" +#include "upb_string.h" #include "upb_table.h" +#include "upb_text.h" diff --git a/src/upb_parse.h b/src/upb_parse.h index 2982b51..09ac4f7 100644 --- a/src/upb_parse.h +++ b/src/upb_parse.h @@ -219,8 +219,8 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } * uint8_t **outbuf); * * // Given an already read wire value s (source), convert it to a .proto - * // value and store it in *d (destination). - * void upb_wvtov_INT32(uint32_t s, int32_t *d); + * // value and return it. + * int32_t upb_wvtov_INT32(uint32_t s); */ #define WVTOV(type, wire_t, val_t) \ diff --git a/src/upb_serialize.h b/src/upb_serialize.h new file mode 100644 index 0000000..39dc79c --- /dev/null +++ b/src/upb_serialize.h @@ -0,0 +1,125 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Implements routines for serializing protobufs. For serializing an entire + * upb_msg, see the serialization routines in upb_msg.h (which are layered on + * top of this). + * + * By default this interface does not "check your work." It doesn't pay + * attention to whether the lengths you give for submessages are correct, or + * whether your groups are properly balanced, or whether you give each value a + * tag of the appropriate type. In other words, it is quite possible (easy, + * even) to use this interface to emit invalid protobufs. We don't want to + * pay for the runtime checks. + * + * The best way to test that you're using the API correctly is to try to parse + * your output. + * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. + */ + +#ifndef UPB_SERIALIZE_H_ +#define UPB_SERIALIZE_H_ + +#include "upb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions to write wire values. ********************************************/ + +/* Puts a varint (wire type: UPB_WIRE_TYPE_VARINT). */ +INLINE upb_status_t upb_put_v_uint64_t(uint8_t *buf, uint8_t *end, uint64_t val, + uint8_t **outbuf) +{ + return UPB_STATUS_OK; +} + +/* Puts a varint -- called when we only have 32 bits of data. */ +INLINE upb_status_t upb_put_v_uint32_t(uint8_t *buf, uint8_t *end, + uint32_t val, uint8_t **outbuf) +{ + return UPB_STATUS_OK; +} + +/* 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) +{ + return UPB_STATUS_OK; +} + +/* Puts a fixed-length 64-bit integer (wire type: UPB_WIRE_TYPE_64BIT). */ +INLINE upb_status_t upb_put_f_uint64_t(uint8_t *buf, uint8_t *end, + uint64_t val, uint8_t **outbuf) +{ + return UPB_STATUS_OK; +} + +/* Functions to write .proto values. ******************************************/ + +/* Performs zig-zag encoding, which is used by sint32 and sint64. */ +INLINE uint32_t upb_zzenc_32(int32_t n) { return (n << 1) ^ (n >> 31); } +INLINE uint64_t upb_zzenc_64(int64_t n) { return (n << 1) ^ (n >> 63); } + +/* Use macros to define a set of two functions for each .proto type: + * + * // Converts and writes a .proto value into buf. "end" indicates the end + * // of the current available buffer (if the buffer does not contain enough + * // space UPB_STATUS_NEED_MORE_DATA is returned). On success, *outbuf will + * // point one past the data that was written. + * upb_status_t upb_put_INT32(uint8_t *buf, uint8_t *end, int32_t val, + * uint8_t **outbuf); + * + * // Given a .proto value s (source) convert it to a wire value. + * uint32_t upb_vtowv_INT32(int32_t s); + */ + +#define VTOWV(type, wire_t, val_t) \ + INLINE wire_t upb_vtowv_ ## type(val_t s) + +#define PUT(type, v_or_f, wire_t, val_t, member_name) \ + INLINE upb_status_t upb_put_ ## type(uint8_t *buf, uint8_t *end, val_t val, \ + uint8_t **outbuf) { \ + wire_t tmp = upb_vtowv_ ## type(val); \ + UPB_CHECK(upb_put_ ## v_or_f ## _ ## wire_t(buf, end, tmp, outbuf)); \ + return UPB_STATUS_OK; \ + } + +#define T(type, v_or_f, wire_t, val_t, member_name) \ + 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) + +T(INT32, v, uint32_t, int32_t, int32) { return (uint32_t)s; } +T(INT64, v, uint64_t, int64_t, int64) { return (uint64_t)s; } +T(UINT32, v, uint32_t, uint32_t, uint32) { return s; } +T(UINT64, v, uint64_t, uint64_t, uint64) { return s; } +T(SINT32, v, uint32_t, int32_t, int32) { return upb_zzenc_32(s); } +T(SINT64, v, uint64_t, int64_t, int64) { return upb_zzdec_64(s); } +T(FIXED32, f, uint32_t, uint32_t, uint32) { return s; } +T(FIXED64, f, uint64_t, uint64_t, uint64) { return s; } +T(SFIXED32, f, uint32_t, int32_t, int32) { return (uint32_t)s; } +T(SFIXED64, f, uint64_t, int64_t, int64) { return (uint64_t)s; } +T(BOOL, v, uint32_t, bool, _bool) { return (uint32_t)s; } +T(ENUM, v, uint32_t, int32_t, int32) { return (uint32_t)s; } +T(DOUBLE, f, uint64_t, double, _double) { + union upb_value v; + v._double = s; + return v.uint64; +} +T(FLOAT, f, uint32_t, float, _float) { + union upb_value v; + v._float = s; + return v.uint32; +} +#undef VTOWV +#undef PUT +#undef T + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_SERIALIZE_H_ */ -- cgit v1.2.3