summaryrefslogtreecommitdiff
path: root/upb/handlers.h
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2014-01-21 18:38:49 -0800
committerJosh Haberman <jhaberman@gmail.com>2014-01-21 18:38:49 -0800
commit0fd2f830882402979a83010e89650e7245960d39 (patch)
tree0968ca9424c5fb2433047519cbd54d3dd8d0b863 /upb/handlers.h
parentce9bba3cb5409844f8f3d7dcc235a9ea30cad090 (diff)
Sync to internal Google development.
Diffstat (limited to 'upb/handlers.h')
-rw-r--r--upb/handlers.h158
1 files changed, 145 insertions, 13 deletions
diff --git a/upb/handlers.h b/upb/handlers.h
index ceb559f..a03c99e 100644
--- a/upb/handlers.h
+++ b/upb/handlers.h
@@ -27,18 +27,26 @@
#ifdef __cplusplus
namespace upb {
+class BufferHandle;
+class BytesHandler;
class HandlerAttributes;
class Handlers;
template <class T> class Handler;
template <class T> struct CanonicalType;
} // namespace upb
+typedef upb::BufferHandle upb_bufhandle;
+typedef upb::BytesHandler upb_byteshandler;
typedef upb::HandlerAttributes upb_handlerattr;
typedef upb::Handlers upb_handlers;
#else
+struct upb_bufhandle;
+struct upb_byteshandler;
struct upb_handlerattr;
struct upb_handlers;
struct upb_sinkframe;
+typedef struct upb_bufhandle upb_bufhandle;
+typedef struct upb_byteshandler upb_byteshandler;
typedef struct upb_handlerattr upb_handlerattr;
typedef struct upb_handlers upb_handlers;
typedef struct upb_sinkframe upb_sinkframe;
@@ -89,12 +97,23 @@ typedef void upb_func();
extern "C" {
#endif
+// Forward-declares for C inline accessors. We need to declare these here
+// so we can "friend" them in the class declarations in C++.
UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
upb_selector_t s);
UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr);
UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
upb_selector_t s);
+UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h);
+UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj,
+ const void *type);
+UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf,
+ size_t ofs);
+UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h);
+UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h);
+UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h);
+
#ifdef __cplusplus
}
#endif
@@ -114,6 +133,7 @@ typedef void upb_handlerfree(void *d);
#ifdef __cplusplus
+// A set of attributes that accompanies a handler's function pointer.
class upb::HandlerAttributes {
public:
HandlerAttributes();
@@ -126,7 +146,27 @@ class upb::HandlerAttributes {
// cleanup handler will be called once for each handler it was successfully
// set on.
bool SetHandlerData(void *handler_data, upb_handlerfree *cleanup);
- void *handler_data() const;
+ const void* handler_data() const;
+
+ // Use this to specify the type of the closure. This will be checked against
+ // all other closure types for handler that use the same closure.
+ // Registration will fail if this does not match all other non-NULL closure
+ // types.
+ bool SetClosureType(const void *closure_type);
+ const void* closure_type() const;
+
+ // Use this to specify the type of the returned closure. Only used for
+ // Start*{String,SubMessage,Sequence} handlers. This must match the closure
+ // type of any handlers that use it (for example, the StringBuf handler must
+ // match the closure returned from StartString).
+ bool SetReturnClosureType(const void *return_closure_type);
+ const void* return_closure_type() const;
+
+ // Set to indicate that the handler always returns "ok" (either "true" or a
+ // non-NULL closure). This is a hint that can allow code generators to
+ // generate more efficient code.
+ bool SetAlwaysOk(bool always_ok);
+ bool always_ok() const;
private:
friend UPB_INLINE const void * ::upb_handlerattr_handlerdata(
@@ -137,15 +177,81 @@ struct upb_handlerattr {
#endif
void *handler_data_;
upb_handlerfree *cleanup;
+ const void *closure_type_;
+ const void *return_closure_type_;
+ bool alwaysok_;
};
+#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, NULL, false}
+
typedef struct {
upb_func *func;
+ // It is wasteful to include the entire attributes here:
+ //
+ // * Some of the information is redundant (like storing the closure type
+ // separately for each handler that must match).
+ // * Some of the info is only needed prior to freeze() (like closure types).
+ // * alignment padding wastes a lot of space for alwaysok_.
+ //
+ // If/when the size and locality of handlers is an issue, we can optimize this
+ // not to store the entire attr like this. We do not expose the table's
+ // layout to allow this optimization in the future.
upb_handlerattr attr;
} upb_handlers_tabent;
#ifdef __cplusplus
+// Extra information about a buffer that is passed to a StringBuf handler.
+// TODO(haberman): allow the handle to be pinned so that it will outlive
+// the handler invocation.
+class upb::BufferHandle {
+ public:
+ BufferHandle();
+ ~BufferHandle();
+
+ // The beginning of the buffer. This may be different than the pointer
+ // passed to a StringBuf handler because the handler may receive data
+ // that is from the middle or end of a larger buffer.
+ const char* buffer() const;
+
+ // The offset within the attached object where this buffer begins. Only
+ // meaningful if there is an attached object.
+ size_t object_offset() const;
+
+ // Note that object_offset is the offset of "buf" within the attached object.
+ void SetBuffer(const char* buf, size_t object_offset);
+
+ // The BufferHandle can have an "attached object", which can be used to
+ // tunnel through a pointer to the buffer's underlying representation.
+ template <class T>
+ void SetAttachedObject(const T* obj);
+
+ // Returns NULL if the attached object is not of this type.
+ template <class T>
+ const T* GetAttachedObject() const;
+
+ private:
+ friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h);
+ friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h,
+ const void *obj,
+ const void *type);
+ friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h,
+ const char *buf, size_t ofs);
+ friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h);
+ friend UPB_INLINE const void* ::upb_bufhandle_objtype(
+ const upb_bufhandle *h);
+ friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h);
+#else
+struct upb_bufhandle {
+#endif
+ const char *buf_;
+ const void *obj_;
+ const void *objtype_;
+ size_t objofs_;
+};
+
+#ifdef __cplusplus
+
// A upb::Handlers object represents the set of handlers associated with a
// message in the graph of messages. You can think of it as a big virtual
// table with functions corresponding to all the events that can fire while
@@ -167,8 +273,8 @@ class upb::Handlers {
typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
typedef Handler<bool (*)(void *, const void *, Status*)> EndMessageHandler;
typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
- typedef Handler<size_t(*)(void *, const void *, const char *, size_t)>
- StringHandler;
+ typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
+ const BufferHandle *)> StringHandler;
template <class T> struct ValueHandler {
typedef Handler<bool(*)(void *, const void *, T)> H;
@@ -224,7 +330,7 @@ class upb::Handlers {
// Freezes the given set of handlers. You may not freeze a handler without
// also freezing any handlers they point to.
static bool Freeze(Handlers*const* handlers, int n, Status* s);
- static bool Freeze(const vector<Handlers*>& handlers, Status* s);
+ static bool Freeze(const std::vector<Handlers*>& handlers, Status* s);
// Returns the msgdef associated with this handlers object.
const MessageDef* message_def() const;
@@ -401,6 +507,9 @@ class upb::Handlers {
// responsibility to cast to the correct function type before calling it.
GenericFunction* GetHandler(Selector selector);
+ // Sets the given attributes to the attributes for this selector.
+ bool GetAttributes(Selector selector, HandlerAttributes* attr);
+
// Returns the handler data that was registered with this handler.
const void* GetHandlerData(Selector selector);
@@ -424,6 +533,7 @@ struct upb_handlers {
upb_refcounted base;
const upb_msgdef *msg;
const upb_handlers **sub;
+ const void *top_closure_type;
upb_status status_; // Used only when mutable.
upb_handlers_tabent table[1]; // Dynamically-sized field handler array.
};
@@ -538,31 +648,38 @@ typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
size_t size_hint);
typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
- size_t n);
-// upb_handlerattr
-#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL}
+ size_t n, const upb_bufhandle* handle);
+// upb_bufhandle
+size_t upb_bufhandle_objofs(const upb_bufhandle *h);
+
+// upb_handlerattr
void upb_handlerattr_init(upb_handlerattr *attr);
void upb_handlerattr_uninit(upb_handlerattr *attr);
bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, void *hd,
upb_handlerfree *cleanup);
+bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type);
+const void *upb_handlerattr_closuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
+ const void *type);
+const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr);
+bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok);
+bool upb_handlerattr_alwaysok(const upb_handlerattr *attr);
+
UPB_INLINE const void *upb_handlerattr_handlerdata(
const upb_handlerattr *attr) {
return attr->handler_data_;
}
-typedef void upb_handlers_callback(void *closure, upb_handlers *h);
-
// upb_handlers
+typedef void upb_handlers_callback(void *closure, upb_handlers *h);
upb_handlers *upb_handlers_new(const upb_msgdef *m,
const void *owner);
const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
const void *owner,
upb_handlers_callback *callback,
void *closure);
-
-// From upb_refcounted.
bool upb_handlers_isfrozen(const upb_handlers *h);
void upb_handlers_ref(const upb_handlers *h, const void *owner);
void upb_handlers_unref(const upb_handlers *h, const void *owner);
@@ -630,17 +747,32 @@ UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
return (upb_func *)h->table[s].func;
}
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
+ upb_handlerattr *attr);
+
UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
upb_selector_t s) {
return upb_handlerattr_handlerdata(&h->table[s].attr);
}
+#ifdef __cplusplus
+
// Handler types for single fields.
// Right now we only have one for TYPE_BYTES but ones for other types
// should follow.
//
// These follow the same handlers protocol for fields of a message.
-typedef struct { upb_handlers_tabent table[3]; } upb_byteshandler;
+class upb::BytesHandler {
+ public:
+ BytesHandler();
+ ~BytesHandler();
+
+ // TODO(haberman): make private and figure out what to friend.
+#else
+struct upb_byteshandler {
+#endif
+ upb_handlers_tabent table[3];
+};
void upb_byteshandler_init(upb_byteshandler *h);
void upb_byteshandler_uninit(upb_byteshandler *h);
@@ -659,7 +791,7 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h,
#ifdef __cplusplus
namespace upb {
-typedef upb_byteshandler BytesHandler;
+typedef upb_byteshandler BytesHandler;
}
#endif
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback