summaryrefslogtreecommitdiff
path: root/upb/sink.c
diff options
context:
space:
mode:
authorJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
committerJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
commit7d3e2bd2c4cfd1296d1d6f996d7548de26540d41 (patch)
treeb4b35967b3322c65cfb1a32220e8718de09d85fc /upb/sink.c
parentea198bdcf947ba4bd51474bdd4f7b82b5e4cf41d (diff)
Sync with 8 months of Google-internal development.
Many things have changed and been simplified. The memory-management story for upb_def and upb_handlers is much more robust; upb_def and upb_handlers should be fairly stable interfaces now. There is still much work to do for the runtime component (upb_sink).
Diffstat (limited to 'upb/sink.c')
-rw-r--r--upb/sink.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/upb/sink.c b/upb/sink.c
new file mode 100644
index 0000000..d829fa9
--- /dev/null
+++ b/upb/sink.c
@@ -0,0 +1,205 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ */
+
+#include "upb/sink.h"
+
+static bool chkstack(upb_sink *s) {
+ if (s->top + 1 >= s->limit) {
+ upb_status_seterrliteral(&s->status, "Nesting too deep.");
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static upb_selector_t getselector(const upb_fielddef *f,
+ upb_handlertype_t type) {
+ upb_selector_t selector;
+ bool ok = upb_getselector(f, type, &selector);
+ UPB_ASSERT_VAR(ok, ok);
+ return selector;
+}
+
+void upb_sink_init(upb_sink *s, const upb_handlers *h) {
+ s->limit = &s->stack[UPB_MAX_NESTING];
+ s->top = NULL;
+ s->stack[0].h = h;
+ upb_status_init(&s->status);
+}
+
+void upb_sink_reset(upb_sink *s, void *closure) {
+ s->top = s->stack;
+ s->top->closure = closure;
+}
+
+void upb_sink_uninit(upb_sink *s) {
+ upb_status_uninit(&s->status);
+}
+
+bool upb_sink_startmsg(upb_sink *s) {
+ const upb_handlers *h = s->top->h;
+ upb_startmsg_handler *startmsg = upb_handlers_getstartmsg(h);
+ return startmsg ? startmsg(s->top->closure) : true;
+}
+
+void upb_sink_endmsg(upb_sink *s, upb_status *status) {
+ UPB_UNUSED(status);
+ assert(s->top == s->stack);
+ upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h);
+ if (endmsg) endmsg(s->top->closure, &s->status);
+}
+
+#define PUTVAL(type, ctype, htype) \
+ bool upb_sink_put ## type(upb_sink *s, const upb_fielddef *f, ctype val) { \
+ upb_selector_t selector; \
+ if (!upb_getselector(f, UPB_HANDLER_ ## htype, &selector)) return false; \
+ upb_ ## type ## _handler *handler = (upb_ ## type ## _handler*) \
+ upb_handlers_gethandler(s->top->h, selector); \
+ if (handler) { \
+ void *data = upb_handlers_gethandlerdata(s->top->h, selector); \
+ if (!handler(s->top->closure, data, val)) return false; \
+ } \
+ return true; \
+ }
+
+PUTVAL(int32, int32_t, INT32);
+PUTVAL(int64, int64_t, INT64);
+PUTVAL(uint32, uint32_t, UINT32);
+PUTVAL(uint64, uint64_t, UINT64);
+PUTVAL(float, float, FLOAT);
+PUTVAL(double, double, DOUBLE);
+PUTVAL(bool, bool, BOOL);
+#undef PUTVAL
+
+size_t upb_sink_putstring(upb_sink *s, const upb_fielddef *f,
+ const char *buf, size_t n) {
+ upb_selector_t selector;
+ if (!upb_getselector(f, UPB_HANDLER_STRING, &selector)) return false;
+ upb_string_handler *handler = (upb_string_handler*)
+ upb_handlers_gethandler(s->top->h, selector);
+ if (handler) {
+ void *data = upb_handlers_gethandlerdata(s->top->h, selector); \
+ return handler(s->top->closure, data, buf, n);
+ }
+ return n;
+}
+
+bool upb_sink_startseq(upb_sink *s, const upb_fielddef *f) {
+ assert(upb_fielddef_isseq(f));
+ if (!chkstack(s)) return false;
+
+ void *subc = s->top->closure;
+ const upb_handlers *h = s->top->h;
+ upb_selector_t selector;
+ if (!upb_getselector(f, UPB_HANDLER_STARTSEQ, &selector)) return false;
+ upb_startfield_handler *startseq =
+ (upb_startfield_handler*)upb_handlers_gethandler(h, selector);
+ if (startseq) {
+ subc = startseq(s->top->closure, upb_handlers_gethandlerdata(h, selector));
+ if (!subc) return false;
+ }
+
+ ++s->top;
+ s->top->end = getselector(f, UPB_HANDLER_ENDSEQ);
+ s->top->h = h;
+ s->top->closure = subc;
+ return true;
+}
+
+bool upb_sink_endseq(upb_sink *s, const upb_fielddef *f) {
+ upb_selector_t selector = s->top->end;
+ assert(selector == getselector(f, UPB_HANDLER_ENDSEQ));
+ --s->top;
+
+ const upb_handlers *h = s->top->h;
+ upb_endfield_handler *endseq =
+ (upb_endfield_handler*)upb_handlers_gethandler(h, selector);
+ return endseq ?
+ endseq(s->top->closure, upb_handlers_gethandlerdata(h, selector)) :
+ true;
+}
+
+bool upb_sink_startstr(upb_sink *s, const upb_fielddef *f, size_t size_hint) {
+ assert(upb_fielddef_isstring(f));
+ if (!chkstack(s)) return false;
+
+ void *subc = s->top->closure;
+ const upb_handlers *h = s->top->h;
+ upb_selector_t selector;
+ if (!upb_getselector(f, UPB_HANDLER_STARTSTR, &selector)) return false;
+ upb_startstr_handler *startstr =
+ (upb_startstr_handler*)upb_handlers_gethandler(h, selector);
+ if (startstr) {
+ subc = startstr(
+ s->top->closure, upb_handlers_gethandlerdata(h, selector), size_hint);
+ if (!subc) return false;
+ }
+
+ ++s->top;
+ s->top->end = getselector(f, UPB_HANDLER_ENDSTR);
+ s->top->h = h;
+ s->top->closure = subc;
+ return true;
+}
+
+bool upb_sink_endstr(upb_sink *s, const upb_fielddef *f) {
+ upb_selector_t selector = s->top->end;
+ assert(selector == getselector(f, UPB_HANDLER_ENDSTR));
+ --s->top;
+
+ const upb_handlers *h = s->top->h;
+ upb_endfield_handler *endstr =
+ (upb_endfield_handler*)upb_handlers_gethandler(h, selector);
+ return endstr ?
+ endstr(s->top->closure, upb_handlers_gethandlerdata(h, selector)) :
+ true;
+}
+
+bool upb_sink_startsubmsg(upb_sink *s, const upb_fielddef *f) {
+ assert(upb_fielddef_issubmsg(f));
+ if (!chkstack(s)) return false;
+
+ const upb_handlers *h = s->top->h;
+ upb_selector_t selector;
+ if (!upb_getselector(f, UPB_HANDLER_STARTSUBMSG, &selector)) return false;
+ upb_startfield_handler *startsubmsg =
+ (upb_startfield_handler*)upb_handlers_gethandler(h, selector);
+ void *subc = s->top->closure;
+
+ if (startsubmsg) {
+ void *data = upb_handlers_gethandlerdata(h, selector);
+ subc = startsubmsg(s->top->closure, data);
+ if (!subc) return false;
+ }
+
+ ++s->top;
+ s->top->end = getselector(f, UPB_HANDLER_ENDSUBMSG);
+ s->top->h = upb_handlers_getsubhandlers(h, f);
+ s->top->closure = subc;
+ upb_sink_startmsg(s);
+ return true;
+}
+
+bool upb_sink_endsubmsg(upb_sink *s, const upb_fielddef *f) {
+ upb_selector_t selector = s->top->end;
+ assert(selector == getselector(f, UPB_HANDLER_ENDSUBMSG));
+
+ upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h);
+ if (endmsg) endmsg(s->top->closure, &s->status);
+ --s->top;
+
+ const upb_handlers *h = s->top->h;
+ upb_endfield_handler *endfield =
+ (upb_endfield_handler*)upb_handlers_gethandler(h, selector);
+ return endfield ?
+ endfield(s->top->closure, upb_handlers_gethandlerdata(h, selector)) :
+ true;
+}
+
+const upb_handlers *upb_sink_tophandlers(upb_sink *s) {
+ return s->top->h;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback