From 15c388b819ebfebb83851950893413041288970f Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Mon, 12 Dec 2016 18:47:55 +0000 Subject: Basic serialization for upb_msg and Lua. Doesn't yet include strings, submessages, maps, or repeated fields. --- upb/sink.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 upb/sink.c (limited to 'upb/sink.c') diff --git a/upb/sink.c b/upb/sink.c new file mode 100644 index 0000000..ed0972b --- /dev/null +++ b/upb/sink.c @@ -0,0 +1,88 @@ + +#include "upb/sink.h" + +bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { + void *subc; + bool ret; + upb_bufhandle handle; + upb_bufhandle_init(&handle); + upb_bufhandle_setbuf(&handle, buf, 0); + ret = upb_bytessink_start(sink, len, &subc); + if (ret && len != 0) { + ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); + } + if (ret) { + ret = upb_bytessink_end(sink); + } + upb_bufhandle_uninit(&handle); + return ret; +} + +struct upb_bufsink { + upb_byteshandler handler; + upb_bytessink sink; + upb_env *env; + char *ptr; + size_t len, size; +}; + +static void *upb_bufsink_start(void *_sink, const void *hd, size_t size_hint) { + upb_bufsink *sink = _sink; + UPB_UNUSED(hd); + UPB_UNUSED(size_hint); + sink->len = 0; + return sink; +} + +static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, + size_t len, const upb_bufhandle *handle) { + upb_bufsink *sink = _sink; + size_t new_size = sink->size; + + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + while (sink->len + len > new_size) { + new_size *= 2; + } + + if (new_size != sink->size) { + sink->ptr = upb_env_realloc(sink->env, sink->ptr, sink->size, new_size); + sink->size = new_size; + } + + memcpy(sink->ptr + sink->len, ptr, len); + sink->len += len; + + return len; +} + +upb_bufsink *upb_bufsink_new(upb_env *env) { + upb_bufsink *sink = upb_env_malloc(env, sizeof(upb_bufsink)); + upb_byteshandler_init(&sink->handler); + upb_byteshandler_setstartstr(&sink->handler, upb_bufsink_start, NULL); + upb_byteshandler_setstring(&sink->handler, upb_bufsink_string, NULL); + + upb_bytessink_reset(&sink->sink, &sink->handler, sink); + + sink->env = env; + sink->size = 32; + sink->ptr = upb_env_malloc(env, sink->size); + sink->len = 0; + + return sink; +} + +void upb_bufsink_free(upb_bufsink *sink) { + upb_env_free(sink->env, sink->ptr); + upb_env_free(sink->env, sink); +} + +upb_bytessink *upb_bufsink_sink(upb_bufsink *sink) { + return &sink->sink; +} + +const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len) { + *len = sink->len; + return sink->ptr; +} -- cgit v1.2.3 From 6cccfe16493c9c88ea198ca37af915179ccf7eaf Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 14 Dec 2016 16:39:04 +0000 Subject: Addressed PR comments. --- upb/msg.c | 30 +++++++++++++++++------------- upb/sink.c | 1 + 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'upb/sink.c') diff --git a/upb/msg.c b/upb/msg.c index 7275338..517b814 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -26,6 +26,7 @@ void *upb_map_pack(const upb_map *map, void *p, size_t *ofs, size_t size); #define CHARPTR_AT(msg, ofs) ((char*)msg + ofs) #define ENCODE_MAX_NESTING 64 +#define CHECK_RETURN(x) if (!(x)) { return false; } /** upb_msgval ****************************************************************/ @@ -502,8 +503,8 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, const upb_msglayout *layout) { - if (upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f)) { - return upb_msgval_getptr(upb_msg_get(msg, f, layout)) != NULL; + if (upb_fielddef_isseq(f)) { + return upb_msgval_getarr(upb_msg_get(msg, f, layout)) != NULL; } else if (upb_msgdef_syntax(upb_fielddef_containingtype(f)) == UPB_SYNTAX_PROTO2) { return upb_msg_has(msg, f, layout); @@ -535,7 +536,7 @@ static bool upb_visitor_hasfield(const upb_msg *msg, const upb_fielddef *f, } } -static void upb_visitor_visitmsg2(const upb_msg *msg, +static bool upb_visitor_visitmsg2(const upb_msg *msg, const upb_msglayout *layout, upb_sink *sink, int depth) { const upb_msgdef *md = upb_msglayout_msgdef(layout); @@ -547,7 +548,7 @@ static void upb_visitor_visitmsg2(const upb_msg *msg, /* Protect against cycles (possible because users may freely reassign message * and repeated fields) by imposing a maximum recursion depth. */ if (depth > ENCODE_MAX_NESTING) { - return; + return false; } for (upb_msg_field_begin(&i, md); @@ -578,26 +579,29 @@ static void upb_visitor_visitmsg2(const upb_msg *msg, switch (upb_fielddef_type(f)) { case UPB_TYPE_FLOAT: - upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val)); + CHECK_RETURN(upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val))); break; case UPB_TYPE_DOUBLE: - upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val)); + CHECK_RETURN( + upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val))); break; case UPB_TYPE_BOOL: - upb_sink_putbool(sink, sel, upb_msgval_getbool(val)); + CHECK_RETURN(upb_sink_putbool(sink, sel, upb_msgval_getbool(val))); break; case UPB_TYPE_ENUM: case UPB_TYPE_INT32: - upb_sink_putint32(sink, sel, upb_msgval_getint32(val)); + CHECK_RETURN(upb_sink_putint32(sink, sel, upb_msgval_getint32(val))); break; case UPB_TYPE_UINT32: - upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val)); + CHECK_RETURN( + upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val))); break; case UPB_TYPE_INT64: - upb_sink_putint64(sink, sel, upb_msgval_getint64(val)); + CHECK_RETURN(upb_sink_putint64(sink, sel, upb_msgval_getint64(val))); break; case UPB_TYPE_UINT64: - upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val)); + CHECK_RETURN( + upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val))); break; case UPB_TYPE_STRING: case UPB_TYPE_BYTES: @@ -608,6 +612,7 @@ static void upb_visitor_visitmsg2(const upb_msg *msg, } upb_sink_endmsg(sink, &status); + return true; } upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, @@ -619,8 +624,7 @@ upb_visitor *upb_visitor_create(upb_env *e, const upb_visitorplan *vp, } bool upb_visitor_visitmsg(upb_visitor *visitor, const upb_msg *msg) { - upb_visitor_visitmsg2(msg, visitor->layout, visitor->sink, 0); - return true; + return upb_visitor_visitmsg2(msg, visitor->layout, visitor->sink, 0); } diff --git a/upb/sink.c b/upb/sink.c index ed0972b..e6ede49 100644 --- a/upb/sink.c +++ b/upb/sink.c @@ -39,6 +39,7 @@ static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, upb_bufsink *sink = _sink; size_t new_size = sink->size; + UPB_ASSERT(new_size > 0); UPB_UNUSED(hd); UPB_UNUSED(handle); -- cgit v1.2.3