summaryrefslogtreecommitdiff
path: root/upb/sink.h
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2013-12-20 17:40:40 -0800
committerJosh Haberman <jhaberman@gmail.com>2013-12-20 17:40:40 -0800
commitce9bba3cb5409844f8f3d7dcc235a9ea30cad090 (patch)
tree6c4e0a7c023c790a278f3616c749280c8da205af /upb/sink.h
parentaa8db6ab5ea18848247b8c4ac4715cf344941e94 (diff)
Sync from Google-internal development.
Diffstat (limited to 'upb/sink.h')
-rw-r--r--upb/sink.h535
1 files changed, 318 insertions, 217 deletions
diff --git a/upb/sink.h b/upb/sink.h
index 27e9fd2..dd2b9f1 100644
--- a/upb/sink.h
+++ b/upb/sink.h
@@ -24,144 +24,64 @@
#ifdef __cplusplus
namespace upb {
-class Pipeline;
+class BufferSource;
+class BytesSink;
class Sink;
-template <int size> class SeededPipeline;
}
-typedef upb::Pipeline upb_pipeline;
+typedef upb::BufferSource upb_bufsrc;
+typedef upb::BytesSink upb_bytessink;
typedef upb::Sink upb_sink;
#else
-struct upb_pipeline;
struct upb_sink;
-typedef struct upb_pipeline upb_pipeline;
+struct upb_bufsrc;
+struct upb_bytessink;
typedef struct upb_sink upb_sink;
+typedef struct upb_bytessink upb_bytessink;
+typedef struct upb_bufsrc upb_bufsrc;
#endif
-struct upb_sinkframe;
-// The maximum nesting depth that upb::Sink will allow. Matches proto2's limit.
-// TODO: make this a runtime-settable property of Sink.
-#define UPB_SINK_MAX_NESTING 64
-
-#ifdef __cplusplus
+// Internal-only struct for the sink.
+struct upb_sinkframe {
+ const upb_handlers *h;
+ void *closure;
-// A upb::Pipeline is a set of sinks that can send data to each other. The
-// pipeline object also contains an arena allocator that the sinks and their
-// associated processing state can use for fast memory allocation. This makes
-// pipelines very fast to construct and destroy, especially if the arena is
-// supplied with an initial block of memory. If this initial block of memory
-// is from the C stack and is large enough, then actual heap allocation can be
-// avoided entirely which significantly reduces overhead in some cases.
-//
-// All sinks and processing state are automatically freed when the pipeline is
-// destroyed, so Free() is not necessary or possible. Allocated objects can
-// optionally specify a Reset() callback that will be called when whenever the
-// pipeline is Reset() or destroyed. This can be used to free any outside
-// resources the object is holding.
-//
-// Pipelines (and sinks/objects allocated from them) are not thread-safe!
-class upb::Pipeline {
- public:
- // Initializes the pipeline's arena with the given initial memory that will
- // be used before allocating memory using the given allocation function.
- // The "ud" pointer will be passed as the first parameter to the realloc
- // callback, and can be used to pass user-specific state.
- Pipeline(void *initial_mem, size_t initial_size,
- void *(*realloc)(void *ud, void *ptr, size_t size), void *ud);
- ~Pipeline();
-
- // Returns a newly-allocated Sink for the given handlers. The sink is will
- // live as long as the pipeline does. Caller retains ownership of the
- // handlers object, which must outlive the pipeline.
+ // For any frames besides the top, this is the END* callback that will run
+ // when the subframe is popped (for example, for a "sequence" frame the frame
+ // above it will be a UPB_HANDLER_ENDSEQ handler). But this is only
+ // necessary for assertion checking inside upb_sink and can be omitted if the
+ // sink has only one caller.
//
- // TODO(haberman): add an option for the sink to take a ref, so the handlers
- // don't have to outlive? This would be simpler but imposes a minimum cost.
- // Taking an atomic ref is not *so* bad in the single-threaded case, but this
- // can degrade heavily under contention, so we need a way to avoid it in
- // cases where this overhead would be significant and the caller can easily
- // guarantee the outlive semantics.
- Sink* NewSink(const Handlers* handlers);
-
- // Accepts a ref donated from the given owner. Will unref the Handlers when
- // the Pipeline is destroyed.
- void DonateRef(const Handlers* h, const void* owner);
-
- // The current error status for the pipeline.
- const upb::Status& status() const;
-
- // Calls "reset" on all Sinks and resettable state objects in the arena, and
- // resets the error status. Useful for resetting processing state so new
- // input can be accepted.
- void Reset();
-
- // Allocates/reallocates memory of the given size, or returns NULL if no
- // memory is available. It is not necessary (or possible) to manually free
- // the memory obtained from these functions.
- void* Alloc(size_t size);
- void* Realloc(void* ptr, size_t old_size, size_t size);
-
- // Allocates an object with the given FrameType. Note that this object may
- // *not* be resized with Realloc().
- void* AllocObject(const FrameType* type);
-
- private:
-#else
-struct upb_pipeline {
-#endif
- void *(*realloc)(void *ud, void *ptr, size_t size);
- void *ud;
- void *bump_top; // Current alloc offset, either from initial or dyn region.
- void *bump_limit; // Limit of current alloc block.
- void *obj_head; // Linked list of objects with "reset" functions.
- void *region_head; // Linked list of dyn regions we got from user's realloc().
- void *last_alloc;
- upb_status status_;
+ // TODO(haberman): have a mechanism for ensuring that a sink only has one
+ // caller.
+ upb_selector_t selector;
};
-struct upb_frametype {
- size_t size;
- void (*init)(void* obj, upb_pipeline *p);
- void (*uninit)(void* obj);
- void (*reset)(void* obj);
-};
+// The maximum nesting depth that upb::Sink will allow. Matches proto2's limit.
+// TODO: make this a runtime-settable property of Sink.
+#define UPB_SINK_MAX_NESTING 64
#ifdef __cplusplus
-// For convenience, a template for a pipeline with an array of initial memory.
-template <int initial_size>
-class upb::SeededPipeline : public upb::Pipeline {
- public:
- SeededPipeline(void *(*realloc)(void *ud, void *ptr, size_t size), void *ud)
- : Pipeline(mem_, initial_size, realloc, ud) {
- }
-
- private:
- char mem_[initial_size];
-};
-
// A upb::Sink is an object that binds a upb::Handlers object to some runtime
-// state. It is the object that can actually call a set of handlers.
-//
-// Unlike upb::Def and upb::Handlers, upb::Sink is never frozen, immutable, or
-// thread-safe. You can create as many of them as you want, but each one may
-// only be used in a single thread at a time.
-//
-// If we compare with class-based OOP, a you can think of a upb::Def as an
-// abstract base class, a upb::Handlers as a concrete derived class, and a
-// upb::Sink as an object (class instance).
-//
-// Each upb::Sink lives in exactly one pipeline.
+// state. It represents an endpoint to which data can be sent.
class upb::Sink {
public:
+ // Constructor with no initialization; must be Reset() before use.
+ Sink() {}
- // Resets the state of the sink so that it is ready to accept new input.
- // Any state from previously received data is discarded. "Closure" will be
- // used as the top-level closure.
- void Reset(void *closure);
+ // Constructs a new sink for the given frozen handlers and closure.
+ //
+ // TODO: once the Handlers know the expected closure type, verify that T
+ // matches it.
+ template <class T> Sink(const Handlers* handlers, T* closure);
- // Returns the pipeline that this sink comes from.
- Pipeline* pipeline() const;
+ // Resets the value of the sink.
+ template <class T> void Reset(const Handlers* handlers, T* closure);
// Returns the top-level object that is bound to this sink.
+ //
+ // TODO: once the Handlers know the expected closure type, verify that T
+ // matches it.
template <class T> T* GetObject() const;
// Functions for pushing data into the sink.
@@ -178,10 +98,10 @@ class upb::Sink {
// sink->StartSubMessage(startsubmsg_selector);
// sink->StartMessage();
// // ...
- // sink->EndMessage();
+ // sink->EndMessage(&status);
// sink->EndSubMessage(endsubmsg_selector);
bool StartMessage();
- bool EndMessage();
+ bool EndMessage(Status* status);
// Putting of individual values. These work for both repeated and
// non-repeated fields, but for repeated fields you must wrap them in
@@ -196,122 +116,306 @@ class upb::Sink {
// Putting of string/bytes values. Each string can consist of zero or more
// non-contiguous buffers of data.
- bool StartString(Handlers::Selector s, size_t size_hint);
+ //
+ // For StartString(), the function will write a sink for the string to "sub."
+ // The sub-sink must be used for any/all PutStringBuffer() calls.
+ bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub);
size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len);
bool EndString(Handlers::Selector s);
// For submessage fields.
- bool StartSubMessage(Handlers::Selector s);
+ //
+ // For StartSubMessage(), the function will write a sink for the string to
+ // "sub." The sub-sink must be used for any/all handlers called within the
+ // submessage.
+ bool StartSubMessage(Handlers::Selector s, Sink* sub);
bool EndSubMessage(Handlers::Selector s);
// For repeated fields of any type, the sequence of values must be wrapped in
// these calls.
- bool StartSequence(Handlers::Selector s);
+ //
+ // For StartSequence(), the function will write a sink for the string to
+ // "sub." The sub-sink must be used for any/all handlers called within the
+ // sequence.
+ bool StartSequence(Handlers::Selector s, Sink* sub);
bool EndSequence(Handlers::Selector s);
- private:
- UPB_DISALLOW_POD_OPS(Sink);
+ // Copy and assign specifically allowed.
+ // We don't even bother making these members private because so many
+ // functions need them and this is mainly just a dumb data container anyway.
#else
struct upb_sink {
#endif
- upb_pipeline *pipeline_;
- struct upb_sinkframe *top, *limit, *stack;
+ const upb_handlers *handlers;
+ void *closure;
};
#ifdef __cplusplus
-extern "C" {
-#endif
-void *upb_realloc(void *ud, void *ptr, size_t size);
-void upb_pipeline_init(upb_pipeline *p, void *initial_mem, size_t initial_size,
- void *(*realloc)(void *ud, void *ptr, size_t size),
- void *ud);
-void upb_pipeline_uninit(upb_pipeline *p);
-void *upb_pipeline_alloc(upb_pipeline *p, size_t size);
-void *upb_pipeline_realloc(
- upb_pipeline *p, void *ptr, size_t old_size, size_t size);
-void *upb_pipeline_allocobj(upb_pipeline *p, const upb_frametype *type);
-void upb_pipeline_reset(upb_pipeline *p);
-void upb_pipeline_donateref(
- upb_pipeline *p, const upb_handlers *h, const void *owner);
-upb_sink *upb_pipeline_newsink(upb_pipeline *p, const upb_handlers *h);
-const upb_status *upb_pipeline_status(const upb_pipeline *p);
-
-void upb_sink_reset(upb_sink *s, void *closure);
-upb_pipeline *upb_sink_pipeline(const upb_sink *s);
-void *upb_sink_getobj(const upb_sink *s);
-bool upb_sink_startmsg(upb_sink *s);
-bool upb_sink_endmsg(upb_sink *s);
-bool upb_sink_putint32(upb_sink *s, upb_selector_t sel, int32_t val);
-bool upb_sink_putint64(upb_sink *s, upb_selector_t sel, int64_t val);
-bool upb_sink_putuint32(upb_sink *s, upb_selector_t sel, uint32_t val);
-bool upb_sink_putuint64(upb_sink *s, upb_selector_t sel, uint64_t val);
-bool upb_sink_putfloat(upb_sink *s, upb_selector_t sel, float val);
-bool upb_sink_putdouble(upb_sink *s, upb_selector_t sel, double val);
-bool upb_sink_putbool(upb_sink *s, upb_selector_t sel, bool val);
-bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, size_t size_hint);
-size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf,
- size_t len);
-bool upb_sink_endstr(upb_sink *s, upb_selector_t sel);
-bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel);
-bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel);
-bool upb_sink_startseq(upb_sink *s, upb_selector_t sel);
-bool upb_sink_endseq(upb_sink *s, upb_selector_t sel);
+class upb::BytesSink {
+ public:
+ BytesSink() {}
+
+ // Constructs a new sink for the given frozen handlers and closure.
+ //
+ // TODO(haberman): once the Handlers know the expected closure type, verify
+ // that T matches it.
+ template <class T> BytesSink(const Handlers* handlers, T* closure);
+
+ // Resets the value of the sink.
+ template <class T> void Reset(const Handlers* handlers, T* closure);
+
+ bool Start(size_t size_hint, void **subc);
+ size_t PutBuffer(void *subc, const char *buf, size_t len);
+ bool End();
+
+#else
+struct upb_bytessink {
+#endif
+ const upb_byteshandler *handler;
+ void *closure;
+};
#ifdef __cplusplus
-} /* extern "C" */
+
+// A class for pushing a flat buffer of data to a BytesSink.
+// You can construct an instance of this to get a resumable source,
+// or just call the static PutBuffer() to do a non-resumable push all in one go.
+class upb::BufferSource {
+ public:
+ BufferSource();
+ BufferSource(const char* buf, size_t len, BytesSink* sink);
+
+ // Returns true if the entire buffer was pushed successfully. Otherwise the
+ // next call to PutNext() will resume where the previous one left off.
+ // TODO(haberman): implement this.
+ bool PutNext();
+
+ // A static version; with this version is it not possible to resume in the
+ // case of failure or a partially-consumed buffer.
+ static bool PutBuffer(const char* buf, size_t len, BytesSink* sink);
+
+ template <class T> static bool PutBuffer(const T& str, BytesSink* sink) {
+ return PutBuffer(str.c_str(), str.size(), sink);
+ }
+
+ private:
+#else
+struct upb_bufsrc {
#endif
+};
#ifdef __cplusplus
+extern "C" {
+#endif
-namespace upb {
+// Inline definitions.
+
+UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h,
+ void *closure) {
+ s->handler = h;
+ s->closure = closure;
+}
+
+UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint,
+ void **subc) {
+ if (!s->handler) return true;
+ upb_startstr_handlerfunc *start =
+ (upb_startstr_handlerfunc *)s->handler->table[UPB_STARTSTR_SELECTOR].func;
+
+ if (!start) return true;
+ *subc = start(s->closure, upb_handlerattr_handlerdata(
+ &s->handler->table[UPB_STARTSTR_SELECTOR].attr),
+ size_hint);
+ return *subc != NULL;
+}
+
+UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc,
+ const char *buf, size_t size) {
+ if (!s->handler) return true;
+ upb_string_handlerfunc *putbuf =
+ (upb_string_handlerfunc *)s->handler->table[UPB_STRING_SELECTOR].func;
+
+ if (!putbuf) return true;
+ return putbuf(subc, upb_handlerattr_handlerdata(
+ &s->handler->table[UPB_STRING_SELECTOR].attr),
+ buf, size);
+}
+
+UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) {
+ if (!s->handler) return true;
+ upb_endfield_handlerfunc *end =
+ (upb_endfield_handlerfunc *)s->handler->table[UPB_ENDSTR_SELECTOR].func;
+
+ if (!end) return true;
+ return end(s->closure,
+ upb_handlerattr_handlerdata(
+ &s->handler->table[UPB_ENDSTR_SELECTOR].attr));
+}
+
+UPB_INLINE bool upb_bufsrc_putbuf(const char *buf, size_t len,
+ upb_bytessink *sink) {
+ void *subc;
+ return
+ upb_bytessink_start(sink, len, &subc) &&
+ (len == 0 || upb_bytessink_putbuf(sink, subc, buf, len) == len) &&
+ upb_bytessink_end(sink);
+}
+#define PUTVAL(type, ctype) \
+ UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \
+ ctype val) { \
+ if (!s->handlers) return true; \
+ upb_##type##_handlerfunc *func = \
+ (upb_##type##_handlerfunc *)upb_handlers_gethandler(s->handlers, sel); \
+ if (!func) return true; \
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel); \
+ return func(s->closure, hd, val); \
+ }
-inline Pipeline::Pipeline(void *initial_mem, size_t initial_size,
- void *(*realloc)(void *ud, void *ptr, size_t size),
- void *ud) {
- upb_pipeline_init(this, initial_mem, initial_size, realloc, ud);
+PUTVAL(int32, int32_t);
+PUTVAL(int64, int64_t);
+PUTVAL(uint32, uint32_t);
+PUTVAL(uint64, uint64_t);
+PUTVAL(float, float);
+PUTVAL(double, double);
+PUTVAL(bool, bool);
+#undef PUTVAL
+
+UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
+ s->handlers = h;
+ s->closure = c;
}
-inline Pipeline::~Pipeline() {
- upb_pipeline_uninit(this);
+
+UPB_INLINE size_t
+upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf, size_t n) {
+ if (!s->handlers) return n;
+ upb_string_handlerfunc *handler =
+ (upb_string_handlerfunc *)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!handler) return n;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ return handler(s->closure, hd, buf, n);
}
-inline void* Pipeline::Alloc(size_t size) {
- return upb_pipeline_alloc(this, size);
+
+UPB_INLINE bool upb_sink_startmsg(upb_sink *s) {
+ if (!s->handlers) return true;
+ upb_startmsg_handlerfunc *startmsg =
+ (upb_startmsg_handlerfunc *)upb_handlers_gethandler(s->handlers,
+ UPB_STARTMSG_SELECTOR);
+ if (!startmsg) return true;
+ const void *hd =
+ upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR);
+ return startmsg(s->closure, hd);
}
-inline void* Pipeline::Realloc(void* ptr, size_t old_size, size_t size) {
- return upb_pipeline_realloc(this, ptr, old_size, size);
+
+UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) {
+ if (!s->handlers) return true;
+ upb_endmsg_handlerfunc *endmsg =
+ (upb_endmsg_handlerfunc *)upb_handlers_gethandler(s->handlers,
+ UPB_ENDMSG_SELECTOR);
+
+ if (!endmsg) return true;
+ const void *hd =
+ upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR);
+ return endmsg(s->closure, hd, status);
}
-inline void* Pipeline::AllocObject(const upb::FrameType* type) {
- return upb_pipeline_allocobj(this, type);
+
+UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel,
+ upb_sink *sub) {
+ sub->closure = s->closure;
+ sub->handlers = s->handlers;
+ if (!s->handlers) return true;
+ upb_startfield_handlerfunc *startseq =
+ (upb_startfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!startseq) return true;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ sub->closure = startseq(s->closure, hd);
+ return sub->closure ? true : false;
}
-inline void Pipeline::Reset() {
- upb_pipeline_reset(this);
+
+UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) {
+ if (!s->handlers) return true;
+ upb_endfield_handlerfunc *endseq =
+ (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!endseq) return true;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ return endseq(s->closure, hd);
}
-inline const upb::Status& Pipeline::status() const {
- return *upb_pipeline_status(this);
+
+UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel,
+ size_t size_hint, upb_sink *sub) {
+ sub->closure = s->closure;
+ sub->handlers = s->handlers;
+ if (!s->handlers) return true;
+ upb_startstr_handlerfunc *startstr =
+ (upb_startstr_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!startstr) return true;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ sub->closure = startstr(s->closure, hd, size_hint);
+ return sub->closure ? true : false;
}
-inline Sink* Pipeline::NewSink(const upb::Handlers* handlers) {
- return upb_pipeline_newsink(this, handlers);
+
+UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) {
+ if (!s->handlers) return true;
+ upb_endfield_handlerfunc *endstr =
+ (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!endstr) return true;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ return endstr(s->closure, hd);
}
-inline void Pipeline::DonateRef(const upb::Handlers* h, const void *owner) {
- return upb_pipeline_donateref(this, h, owner);
+
+UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel,
+ upb_sink *sub) {
+ sub->closure = s->closure;
+ if (!s->handlers) {
+ sub->handlers = NULL;
+ return true;
+ }
+ sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel);
+ upb_startfield_handlerfunc *startsubmsg =
+ (upb_startfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!startsubmsg) return true;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ sub->closure = startsubmsg(s->closure, hd);
+ return sub->closure ? true : false;
}
-inline void Sink::Reset(void *closure) {
- upb_sink_reset(this, closure);
+UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
+ if (!s->handlers) return true;
+ upb_endfield_handlerfunc *endsubmsg =
+ (upb_endfield_handlerfunc*)upb_handlers_gethandler(s->handlers, sel);
+
+ if (!endsubmsg) return s->closure;
+ const void *hd = upb_handlers_gethandlerdata(s->handlers, sel);
+ return endsubmsg(s->closure, hd);
}
-inline Pipeline* Sink::pipeline() const {
- return upb_sink_pipeline(this);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#ifdef __cplusplus
+
+namespace upb {
+
+template <class T> Sink::Sink(const Handlers* handlers, T* closure) {
+ upb_sink_reset(this, handlers, closure);
}
template <class T>
-inline T* Sink::GetObject() const {
- return static_cast<T*>(upb_sink_getobj(this));
+inline void Sink::Reset(const Handlers* handlers, T* closure) {
+ upb_sink_reset(this, handlers, closure);
}
inline bool Sink::StartMessage() {
return upb_sink_startmsg(this);
}
-inline bool Sink::EndMessage() {
- return upb_sink_endmsg(this);
+inline bool Sink::EndMessage(Status* status) {
+ return upb_sink_endmsg(this, status);
}
inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) {
return upb_sink_putint32(this, sel, val);
@@ -334,8 +438,9 @@ inline bool Sink::PutDouble(Handlers::Selector sel, double val) {
inline bool Sink::PutBool(Handlers::Selector sel, bool val) {
return upb_sink_putbool(this, sel, val);
}
-inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint) {
- return upb_sink_startstr(this, sel, size_hint);
+inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint,
+ Sink *sub) {
+ return upb_sink_startstr(this, sel, size_hint, sub);
}
inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf,
size_t len) {
@@ -344,39 +449,35 @@ inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf,
inline bool Sink::EndString(Handlers::Selector sel) {
return upb_sink_endstr(this, sel);
}
-inline bool Sink::StartSubMessage(Handlers::Selector sel) {
- return upb_sink_startsubmsg(this, sel);
+inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) {
+ return upb_sink_startsubmsg(this, sel, sub);
}
inline bool Sink::EndSubMessage(Handlers::Selector sel) {
return upb_sink_endsubmsg(this, sel);
}
-inline bool Sink::StartSequence(Handlers::Selector sel) {
- return upb_sink_startseq(this, sel);
+inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) {
+ return upb_sink_startseq(this, sel, sub);
}
inline bool Sink::EndSequence(Handlers::Selector sel) {
return upb_sink_endseq(this, sel);
}
-} // namespace upb
-#endif
+inline bool BytesSink::Start(size_t size_hint, void **subc) {
+ return upb_bytessink_start(this, size_hint, subc);
+}
+inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len) {
+ return upb_bytessink_putbuf(this, subc, buf, len);
+}
+inline bool BytesSink::End() {
+ return upb_bytessink_end(this);
+}
-// TODO(haberman): move this to sink.c. We keep it here now only because the
-// JIT needs to modify it directly, which it only needs to do because it makes
-// the interpreter handle fallback cases. When the JIT is self-sufficient, it
-// will no longer need to touch the sink's stack at all.
-struct upb_sinkframe {
- const upb_handlers *h;
- void *closure;
+inline bool BufferSource::PutBuffer(const char *buf, size_t len,
+ BytesSink *sink) {
+ return upb_bufsrc_putbuf(buf, len, sink);
+}
- // For any frames besides the top, this is the END* callback that will run
- // when the subframe is popped (for example, for a "sequence" frame the frame
- // above it will be a UPB_HANDLER_ENDSEQ handler). But this is only
- // necessary for assertion checking inside upb_sink and can be omitted if the
- // sink has only one caller.
- //
- // TODO(haberman): have a mechanism for ensuring that a sink only has one
- // caller.
- upb_selector_t selector;
-};
+} // namespace upb
+#endif
#endif
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback