summaryrefslogtreecommitdiff
path: root/src/upb_serialize.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/upb_serialize.h')
-rw-r--r--src/upb_serialize.h125
1 files changed, 125 insertions, 0 deletions
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_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback