diff options
author | Josh Haberman <jhaberman@gmail.com> | 2014-07-02 15:41:10 -0700 |
---|---|---|
committer | Josh Haberman <jhaberman@gmail.com> | 2014-07-02 15:41:10 -0700 |
commit | 47b5e0968aa0ec47f522ba357c159b2450645806 (patch) | |
tree | d8cd2e7d518b1d6572a6002843446c9e6ee8ef89 /upb/sink.h | |
parent | 2d10fa33071d52d7a35ce3b13bc459cd16a0aa33 (diff) |
Sync from internal Google development.
Diffstat (limited to 'upb/sink.h')
-rw-r--r-- | upb/sink.h | 93 |
1 files changed, 53 insertions, 40 deletions
@@ -28,20 +28,15 @@ class BufferSource; class BytesSink; class Sink; } -typedef upb::BufferSource upb_bufsrc; -typedef upb::BytesSink upb_bytessink; -typedef upb::Sink upb_sink; -#else -struct upb_sink; -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 +UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc); +UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink); +UPB_DECLARE_TYPE(upb::Sink, upb_sink); + // Internal-only struct for the sink. struct upb_sinkframe { + UPB_PRIVATE_FOR_CPP const upb_handlers *h; void *closure; @@ -60,11 +55,43 @@ struct upb_sinkframe { // TODO: make this a runtime-settable property of Sink. #define UPB_SINK_MAX_NESTING 64 -#ifdef __cplusplus - // A upb::Sink is an object that binds a upb::Handlers object to some runtime // state. It represents an endpoint to which data can be sent. -class upb::Sink { +// +// TODO(haberman): right now all of these functions take selectors. Should they +// take selectorbase instead? +// +// ie. instead of calling: +// sink->StartString(FOO_FIELD_START_STRING, ...) +// a selector base would let you say: +// sink->StartString(FOO_FIELD, ...) +// +// This would make call sites a little nicer and require emitting fewer selector +// definitions in .h files. +// +// But the current scheme has the benefit that you can retrieve a function +// pointer for any handler with handlers->GetHandler(selector), without having +// to have a separate GetHandler() function for each handler type. The JIT +// compiler uses this. To accommodate we'd have to expose a separate +// GetHandler() for every handler type. +// +// Also to ponder: selectors right now are independent of a specific Handlers +// instance. In other words, they allocate a number to every possible handler +// that *could* be registered, without knowing anything about what handlers +// *are* registered. That means that using selectors as table offsets prohibits +// us from compacting the handler table at Freeze() time. If the table is very +// sparse, this could be wasteful. +// +// Having another selector-like thing that is specific to a Handlers instance +// would allow this compacting, but then it would be impossible to write code +// ahead-of-time that can be bound to any Handlers instance at runtime. For +// example, a .proto file parser written as straight C will not know what +// Handlers it will be bound to, so when it calls sink->StartString() what +// selector will it pass? It needs a selector like we have today, that is +// independent of any particular upb::Handlers. +// +// Is there a way then to allow Handlers table compaction? +UPB_DEFINE_CLASS0(upb::Sink, public: // Constructor with no initialization; must be Reset() before use. Sink() {} @@ -144,16 +171,13 @@ class upb::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_DEFINE_STRUCT0(upb_sink, const upb_handlers *handlers; void *closure; -}; +)); -#ifdef __cplusplus - -class upb::BytesSink { +UPB_DEFINE_CLASS0(upb::BytesSink, public: BytesSink() {} @@ -170,20 +194,16 @@ class upb::BytesSink { size_t PutBuffer(void *subc, const char *buf, size_t len, const BufferHandle *handle); bool End(); - -#else -struct upb_bytessink { -#endif +, +UPB_DEFINE_STRUCT0(upb_bytessink, const upb_byteshandler *handler; void *closure; -}; - -#ifdef __cplusplus +)); // 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 { +UPB_DEFINE_CLASS0(upb::BufferSource, public: BufferSource(); BufferSource(const char* buf, size_t len, BytesSink* sink); @@ -200,16 +220,11 @@ class upb::BufferSource { template <class T> static bool PutBuffer(const T& str, BytesSink* sink) { return PutBuffer(str.c_str(), str.size(), sink); } +, +UPB_DEFINE_STRUCT0(upb_bufsrc, +)); - private: -#else -struct upb_bufsrc { -#endif -}; - -#ifdef __cplusplus -extern "C" { -#endif +UPB_BEGIN_EXTERN_C // { // Inline definitions. @@ -409,9 +424,7 @@ UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { return endsubmsg(s->closure, hd); } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_END_EXTERN_C // } #ifdef __cplusplus |