summaryrefslogtreecommitdiff
path: root/upb/sink.h
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2014-07-02 15:41:10 -0700
committerJosh Haberman <jhaberman@gmail.com>2014-07-02 15:41:10 -0700
commit47b5e0968aa0ec47f522ba357c159b2450645806 (patch)
treed8cd2e7d518b1d6572a6002843446c9e6ee8ef89 /upb/sink.h
parent2d10fa33071d52d7a35ce3b13bc459cd16a0aa33 (diff)
Sync from internal Google development.
Diffstat (limited to 'upb/sink.h')
-rw-r--r--upb/sink.h93
1 files changed, 53 insertions, 40 deletions
diff --git a/upb/sink.h b/upb/sink.h
index d2bb095..4e3216b 100644
--- a/upb/sink.h
+++ b/upb/sink.h
@@ -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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback