parent
60e7933d4c
commit
cd3d737d5e
3 changed files with 131 additions and 2 deletions
@ -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_ */ |
Loading…
Reference in new issue