summaryrefslogtreecommitdiff
path: root/core/upb_stream_vtbl.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/upb_stream_vtbl.h')
-rw-r--r--core/upb_stream_vtbl.h96
1 files changed, 78 insertions, 18 deletions
diff --git a/core/upb_stream_vtbl.h b/core/upb_stream_vtbl.h
index d017177..e462122 100644
--- a/core/upb_stream_vtbl.h
+++ b/core/upb_stream_vtbl.h
@@ -13,6 +13,7 @@
#include <assert.h>
#include "upb_stream.h"
+#include "upb_string.h"
#ifdef __cplusplus
extern "C" {
@@ -21,10 +22,8 @@ extern "C" {
// Typedefs for function pointers to all of the virtual functions.
// upb_src
-struct _upb_src {
-};
-typedef struct {
-} upb_src_vtbl;
+typedef void (*upb_src_sethandlers_fptr)(upb_src *src, upb_handlers *handlers);
+typedef void (*upb_src_run_fptr)(upb_src *src, upb_status *status);
// upb_bytesrc.
typedef upb_strlen_t (*upb_bytesrc_read_fptr)(
@@ -42,42 +41,65 @@ typedef upb_strlen_t (*upb_bytesink_putstr_fptr)(
typedef struct {
upb_bytesrc_read_fptr read;
upb_bytesrc_getstr_fptr getstr;
-} upb_bytesrc_vtable;
+} upb_bytesrc_vtbl;
typedef struct {
upb_bytesink_write_fptr write;
upb_bytesink_putstr_fptr putstr;
-} upb_bytesink_vtable;
+} upb_bytesink_vtbl;
+
+typedef struct {
+ upb_src_sethandlers_fptr sethandlers;
+ upb_src_run_fptr run;
+} upb_src_vtbl;
+
// "Base Class" definitions; components that implement these interfaces should
// contain one of these structures.
struct _upb_bytesrc {
- upb_bytesrc_vtable *vtbl;
+ upb_bytesrc_vtbl *vtbl;
upb_status status;
bool eof;
};
struct _upb_bytesink {
- upb_bytesink_vtable *vtbl;
+ upb_bytesink_vtbl *vtbl;
upb_status status;
bool eof;
};
-INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtable *vtbl) {
+struct _upb_src {
+ upb_src_vtbl *vtbl;
+};
+
+INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) {
s->vtbl = vtbl;
s->eof = false;
upb_status_init(&s->status);
}
-INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtable *vtbl) {
+INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) {
s->vtbl = vtbl;
s->eof = false;
upb_status_init(&s->status);
}
+INLINE void upb_src_init(upb_src *s, upb_src_vtbl *vtbl) {
+ s->vtbl = vtbl;
+}
+
// Implementation of virtual function dispatch.
+// upb_src
+INLINE void upb_src_sethandlers(upb_src *src, upb_handlers *handlers) {
+ src->vtbl->sethandlers(src, handlers);
+}
+
+INLINE void upb_src_run(upb_src *src, upb_status *status) {
+ src->vtbl->run(src, status);
+}
+
// upb_bytesrc
INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf,
upb_strlen_t count) {
@@ -152,7 +174,41 @@ INLINE bool upb_handlers_isempty(upb_handlers *h) {
return !h->set && !h->closure;
}
+INLINE upb_flow_t upb_nop(void *closure) {
+ (void)closure;
+ return UPB_CONTINUE;
+}
+
+INLINE upb_flow_t upb_value_nop(void *closure, struct _upb_fielddef *f, upb_value val) {
+ (void)closure;
+ (void)f;
+ (void)val;
+ return UPB_CONTINUE;
+}
+
+INLINE upb_flow_t upb_startsubmsg_nop(void *closure, struct _upb_fielddef *f,
+ upb_handlers *delegate_to) {
+ (void)closure;
+ (void)f;
+ (void)delegate_to;
+ return UPB_CONTINUE;
+}
+
+INLINE upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum,
+ upb_value val) {
+ (void)closure;
+ (void)fieldnum;
+ (void)val;
+ return UPB_CONTINUE;
+}
+
INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set) {
+ if (!set->startmsg) set->startmsg = &upb_nop;
+ if (!set->endmsg) set->endmsg = &upb_nop;
+ if (!set->value) set->value = &upb_value_nop;
+ if (!set->startsubmsg) set->startsubmsg = &upb_startsubmsg_nop;
+ if (!set->endsubmsg) set->endsubmsg = &upb_nop;
+ if (!set->unknownval) set->unknownval = &upb_unknownval_nop;
h->set = set;
}
@@ -182,16 +238,19 @@ INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h) {
d->top->handlers = *h;
}
-INLINE void upb_dispatch_startmsg(upb_dispatcher *d) {
+INLINE upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d) {
assert(d->stack == d->top);
- d->top->handlers.set->startmsg(d->top->handlers.closure);
+ return d->top->handlers.set->startmsg(d->top->handlers.closure);
}
-INLINE void upb_dispatch_endmsg(upb_dispatcher *d) {
+INLINE upb_flow_t upb_dispatch_endmsg(upb_dispatcher *d) {
assert(d->stack == d->top);
- d->top->handlers.set->endmsg(d->top->handlers.closure);
+ return d->top->handlers.set->endmsg(d->top->handlers.closure);
}
+// TODO: several edge cases to fix:
+// - delegated start returns UPB_BREAK, should replay the start on resume.
+// - endsubmsg returns UPB_BREAK, should NOT replay the delegated endmsg.
INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
struct _upb_fielddef *f) {
upb_handlers handlers;
@@ -203,17 +262,18 @@ INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
++d->top;
d->top->handlers = handlers;
d->top->depth = 0;
- d->top->handlers.set->startmsg(d->top->handlers.closure);
- ret = UPB_CONTINUE;
+ ret = d->top->handlers.set->startmsg(d->top->handlers.closure);
}
- ++d->top->depth;
+ if (ret == UPB_CONTINUE) ++d->top->depth;
upb_handlers_uninit(&handlers);
return ret;
}
INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d) {
+ upb_flow_t ret;
if (--d->top->depth == 0) {
- d->top->handlers.set->endmsg(d->top->handlers.closure);
+ ret = d->top->handlers.set->endmsg(d->top->handlers.closure);
+ if (ret != UPB_CONTINUE) return ret;
--d->top;
}
return d->top->handlers.set->endsubmsg(d->top->handlers.closure);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback