summaryrefslogtreecommitdiff
path: root/upb/handlers.h
diff options
context:
space:
mode:
Diffstat (limited to 'upb/handlers.h')
-rw-r--r--upb/handlers.h846
1 files changed, 372 insertions, 474 deletions
diff --git a/upb/handlers.h b/upb/handlers.h
index a4e2a04..e267f12 100644
--- a/upb/handlers.h
+++ b/upb/handlers.h
@@ -24,20 +24,13 @@
#ifdef __cplusplus
namespace upb {
-class BufferHandle;
-class BytesHandler;
-class HandlerAttributes;
-class Handlers;
+class HandlersPtr;
+class HandlerCache;
template <class T> class Handler;
template <class T> struct CanonicalType;
} /* namespace upb */
#endif
-UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle)
-UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler)
-UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr)
-UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted,
- upb_handlers, upb_refcounted)
/* The maximum depth that the handler graph can have. This is a resource limit
* for the C stack since we sometimes need to recursively traverse the graph.
@@ -79,28 +72,6 @@ extern char _upb_noclosure;
* (for example: the STARTSUBMSG handler for field "field15"). */
typedef int32_t upb_selector_t;
-UPB_BEGIN_EXTERN_C
-
-/* 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);
-
-UPB_END_EXTERN_C
-
-
/* Static selectors for upb::Handlers. */
#define UPB_STARTMSG_SELECTOR 0
#define UPB_ENDMSG_SELECTOR 1
@@ -112,125 +83,236 @@ UPB_END_EXTERN_C
#define UPB_STRING_SELECTOR 1
#define UPB_ENDSTR_SELECTOR 2
-typedef void upb_handlerfree(void *d);
-
#ifdef __cplusplus
-
-/* A set of attributes that accompanies a handler's function pointer. */
-class upb::HandlerAttributes {
- public:
- HandlerAttributes();
- ~HandlerAttributes();
-
- /* Sets the handler data that will be passed as the second parameter of the
- * handler. To free this pointer when the handlers are freed, call
- * Handlers::AddCleanup(). */
- bool SetHandlerData(const void *handler_data);
- 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(
- const upb_handlerattr *attr);
-#else
-struct upb_handlerattr {
+template<class T> const void *UniquePtrForType() {
+ static const char ch = 0;
+ return &ch;
+}
#endif
- const void *handler_data_;
- const void *closure_type_;
- const void *return_closure_type_;
- bool alwaysok_;
-};
-#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false}
+/* upb_handlers ************************************************************/
+/* Handler attributes, to be registered with the handler itself. */
typedef struct {
- upb_func *func;
+ const void *handler_data;
+ const void *closure_type;
+ const void *return_closure_type;
+ bool alwaysok;
+} upb_handlerattr;
- /* 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();
+#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false}
+/* Bufhandle, data passed along with a buffer to indicate its provenance. */
+typedef struct {
/* 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;
+ const char *buf;
/* The offset within the attached object where this buffer begins. Only
* meaningful if there is an attached object. */
- size_t object_offset() const;
+ size_t objofs;
- /* Note that object_offset is the offset of "buf" within the attached
- * object. */
- void SetBuffer(const char* buf, size_t object_offset);
+ /* The attached object (if any) and a pointer representing its type. */
+ const void *obj;
+ const void *objtype;
- /* The BufferHandle can have an "attached object", which can be used to
- * tunnel through a pointer to the buffer's underlying representation. */
+#ifdef __cplusplus
template <class T>
- void SetAttachedObject(const T* obj);
+ void SetAttachedObject(const T* _obj) {
+ obj = _obj;
+ objtype = UniquePtrForType<T>();
+ }
- /* Returns NULL if the attached object is not of this type. */
template <class T>
- const T* GetAttachedObject() const;
+ const T *GetAttachedObject() const {
+ return objtype == UniquePtrForType<T>() ? static_cast<const T *>(obj)
+ : NULL;
+ }
+#endif
+} upb_bufhandle;
- 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 {
+#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL}
+
+/* Handler function typedefs. */
+typedef void upb_handlerfree(void *d);
+typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
+ size_t n);
+typedef bool upb_startmsg_handlerfunc(void *c, const void*);
+typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
+typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
+typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
+typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
+typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
+typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
+typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
+typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
+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, const upb_bufhandle* handle);
+
+struct upb_handlers;
+typedef struct upb_handlers upb_handlers;
+
+#ifdef __cplusplus
+extern "C" {
#endif
- const char *buf_;
- const void *obj_;
- const void *objtype_;
- size_t objofs_;
-};
+
+/* Mutating accessors. */
+const upb_status *upb_handlers_status(upb_handlers *h);
+void upb_handlers_clearerr(upb_handlers *h);
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
+bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
+bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
+ upb_int32_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
+ upb_int64_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
+ upb_uint32_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
+ upb_uint64_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
+ upb_float_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
+ upb_double_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
+ upb_bool_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
+ upb_startstr_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
+ upb_string_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
+ upb_startfield_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
+ upb_startfield_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handlerfunc *func,
+ const upb_handlerattr *attr);
+bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handlerfunc *func,
+ const upb_handlerattr *attr);
+
+/* Read-only accessors. */
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+ const upb_fielddef *f);
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+ upb_selector_t sel);
+upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
+ const void **handler_data);
+bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
+ upb_handlerattr *attr);
+
+/* "Static" methods */
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+ upb_selector_t *s);
+UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
+ return start + 1;
+}
+
+/* Internal-only. */
+uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
+uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
#ifdef __cplusplus
+} /* extern "C" */
+
+namespace upb {
+typedef upb_handlers Handlers;
+}
+
+/* Convenience macros for creating a Handler object that is wrapped with a
+ * type-safe wrapper function that converts the "void*" parameters/returns
+ * of the underlying C API into nice C++ function.
+ *
+ * Sample usage:
+ * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
+ * // do stuff ...
+ * }
+ *
+ * // Handler that doesn't need any data bound to it.
+ * void OnValue2(MyClosure* c, int32_t val) {
+ * // do stuff ...
+ * }
+ *
+ * // Handler that returns bool so it can return failure if necessary.
+ * bool OnValue3(MyClosure* c, int32_t val) {
+ * // do stuff ...
+ * return ok;
+ * }
+ *
+ * // Member function handler.
+ * class MyClosure {
+ * public:
+ * void OnValue(int32_t val) {
+ * // do stuff ...
+ * }
+ * };
+ *
+ * // Takes ownership of the MyHandlerData.
+ * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
+ * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
+ * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
+ * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
+ */
+
+/* In C++11, the "template" disambiguator can appear even outside templates,
+ * so all calls can safely use this pair of macros. */
+
+#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
+
+/* We have to be careful to only evaluate "d" once. */
+#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+
+/* Handler: a struct that contains the (handler, data, deleter) tuple that is
+ * used to register all handlers. Users can Make() these directly but it's
+ * more convenient to use the UpbMakeHandler/UpbBind macros above. */
+template <class T> class upb::Handler {
+ public:
+ /* The underlying, handler function signature that upb uses internally. */
+ typedef T FuncPtr;
+
+ /* Intentionally implicit. */
+ template <class F> Handler(F func);
+ ~Handler() { UPB_ASSERT(registered_); }
+
+ void AddCleanup(upb_handlers* h) const;
+ FuncPtr handler() const { return handler_; }
+ const upb_handlerattr& attr() const { return attr_; }
+
+ private:
+ Handler(const Handler&) = delete;
+ Handler& operator=(const Handler&) = delete;
+
+ FuncPtr handler_;
+ mutable upb_handlerattr attr_;
+ mutable bool registered_;
+ void *cleanup_data_;
+ upb_handlerfree *cleanup_func_;
+};
/* 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
@@ -243,18 +325,24 @@ struct upb_bufhandle {
*
* The easiest way to create the *Handler objects needed by the Set* methods is
* with the UpbBind() and UpbMakeHandler() macros; see below. */
-class upb::Handlers {
+class upb::HandlersPtr {
public:
+ HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {}
+
+ upb_handlers* ptr() const { return ptr_; }
+
typedef upb_selector_t Selector;
typedef upb_handlertype_t Type;
typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
- typedef Handler<bool (*)(void *, const void *, Status*)> EndMessageHandler;
+ typedef Handler<bool (*)(void *, const void *, upb_status *)>
+ EndMessageHandler;
typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
- const BufferHandle *)> StringHandler;
+ const upb_bufhandle *)>
+ StringHandler;
template <class T> struct ValueHandler {
typedef Handler<bool(*)(void *, const void *, T)> H;
@@ -274,47 +362,17 @@ class upb::Handlers {
typedef void HandlersCallback(const void *closure, upb_handlers *h);
- /* Returns a new handlers object for the given frozen msgdef.
- * Returns NULL if memory allocation failed. */
- static reffed_ptr<Handlers> New(const MessageDef *m);
-
- /* Convenience function for registering a graph of handlers that mirrors the
- * graph of msgdefs for some message. For "m" and all its children a new set
- * of handlers will be created and the given callback will be invoked,
- * allowing the client to register handlers for this message. Note that any
- * subhandlers set by the callback will be overwritten. */
- static reffed_ptr<const Handlers> NewFrozen(const MessageDef *m,
- HandlersCallback *callback,
- const void *closure);
-
- /* Functionality from upb::RefCounted. */
- UPB_REFCOUNTED_CPPMETHODS
-
- /* All handler registration functions return bool to indicate success or
- * failure; details about failures are stored in this status object. If a
- * failure does occur, it must be cleared before the Handlers are frozen,
- * otherwise the freeze() operation will fail. The functions may *only* be
- * used while the Handlers are mutable. */
- const Status* status();
- void ClearError();
-
- /* Call to freeze these Handlers. Requires that any SubHandlers are already
- * frozen. For cycles, you must use the static version below and freeze the
- * whole graph at once. */
- bool Freeze(Status* s);
-
- /* 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 std::vector<Handlers*>& handlers, Status* s);
-
/* Returns the msgdef associated with this handlers object. */
- const MessageDef* message_def() const;
+ MessageDefPtr message_def() const {
+ return MessageDefPtr(upb_handlers_msgdef(ptr()));
+ }
/* Adds the given pointer and function to the list of cleanup functions that
* will be run when these handlers are freed. If this pointer has previously
* been registered, the function returns false and does nothing. */
- bool AddCleanup(void *ptr, upb_handlerfree *cleanup);
+ bool AddCleanup(void *ptr, upb_handlerfree *cleanup) {
+ return upb_handlers_addcleanup(ptr_, ptr, cleanup);
+ }
/* Sets the startmsg handler for the message, which is defined as follows:
*
@@ -324,7 +382,10 @@ class upb::Handlers {
* return true;
* }
*/
- bool SetStartMessageHandler(const StartMessageHandler& handler);
+ bool SetStartMessageHandler(const StartMessageHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr());
+ }
/* Sets the endmsg handler for the message, which is defined as follows:
*
@@ -334,7 +395,10 @@ class upb::Handlers {
* // can also be modified in-place to update the final status.
* }
*/
- bool SetEndMessageHandler(const EndMessageHandler& handler);
+ bool SetEndMessageHandler(const EndMessageHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr());
+ }
/* Sets the value handler for the given field, which is defined as follows
* (this is for an int32 field; other field types will pass their native
@@ -356,13 +420,40 @@ class upb::Handlers {
* Returns false if the handler failed to register; in this case the cleanup
* handler (if any) will be called immediately.
*/
- bool SetInt32Handler (const FieldDef* f, const Int32Handler& h);
- bool SetInt64Handler (const FieldDef* f, const Int64Handler& h);
- bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h);
- bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h);
- bool SetFloatHandler (const FieldDef* f, const FloatHandler& h);
- bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h);
- bool SetBoolHandler (const FieldDef* f, const BoolHandler& h);
+ bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetInt64Handler (FieldDefPtr f, const Int64Handler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetFloatHandler (FieldDefPtr f, const FloatHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
/* Like the previous, but templated on the type on the value (ie. int32).
* This is mostly useful to call from other templates. To call this you must
@@ -370,8 +461,8 @@ class upb::Handlers {
* h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
template <class T>
bool SetValueHandler(
- const FieldDef *f,
- const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler);
+ FieldDefPtr f,
+ const typename ValueHandler<typename CanonicalType<T>::Type>::H &handler);
/* Sets handlers for a string field, which are defined as follows:
*
@@ -409,9 +500,20 @@ class upb::Handlers {
* return true;
* }
*/
- bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h);
- bool SetStringHandler(const FieldDef* f, const StringHandler& h);
- bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h);
+ bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetStringHandler(FieldDefPtr f, const StringHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
+
+ bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
/* Sets the startseq handler, which is defined as follows:
*
@@ -427,7 +529,10 @@ class upb::Handlers {
* Returns "false" if "f" does not belong to this message or is not a
* repeated field.
*/
- bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h);
+ bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
/* Sets the startsubmsg handler for the given field, which is defined as
* follows:
@@ -444,7 +549,10 @@ class upb::Handlers {
* Returns "false" if "f" does not belong to this message or is not a
* submessage/group field.
*/
- bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h);
+ bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
/* Sets the endsubmsg handler for the given field, which is defined as
* follows:
@@ -457,7 +565,10 @@ class upb::Handlers {
* Returns "false" if "f" does not belong to this message or is not a
* submessage/group field.
*/
- bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h);
+ bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
/* Starts the endsubseq handler for the given field, which is defined as
* follows:
@@ -470,315 +581,102 @@ class upb::Handlers {
* Returns "false" if "f" does not belong to this message or is not a
* repeated field.
*/
- bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h);
-
- /* Sets or gets the object that specifies handlers for the given field, which
- * must be a submessage or group. Returns NULL if no handlers are set. */
- bool SetSubHandlers(const FieldDef* f, const Handlers* sub);
- const Handlers* GetSubHandlers(const FieldDef* f) const;
-
- /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the
- * field. */
- const Handlers* GetSubHandlers(Selector startsubmsg) const;
-
- /* A selector refers to a specific field handler in the Handlers object
- * (for example: the STARTSUBMSG handler for field "field15").
- * On success, returns true and stores the selector in "s".
- * If the FieldDef or Type are invalid, returns false.
- * The returned selector is ONLY valid for Handlers whose MessageDef
- * contains this FieldDef. */
- static bool GetSelector(const FieldDef* f, Type type, Selector* s);
-
- /* Given a START selector of any kind, returns the corresponding END selector. */
- static Selector GetEndSelector(Selector start_selector);
-
- /* Returns the function pointer for this handler. It is the client's
- * 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);
-
- /* Could add any of the following functions as-needed, with some minor
- * implementation changes:
- *
- * const FieldDef* GetFieldDef(Selector selector);
- * static bool IsSequence(Selector selector); */
+ bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) {
+ h.AddCleanup(ptr());
+ return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr());
+ }
private:
- UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers)
-
- friend UPB_INLINE GenericFunction *::upb_handlers_gethandler(
- const upb_handlers *h, upb_selector_t s);
- friend UPB_INLINE const void *::upb_handlers_gethandlerdata(
- const upb_handlers *h, upb_selector_t s);
-#else
-struct upb_handlers {
-#endif
- upb_refcounted base;
-
- const upb_msgdef *msg;
- const upb_handlers **sub;
- const void *top_closure_type;
- upb_inttable cleanup_;
- upb_status status_; /* Used only when mutable. */
- upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */
+ upb_handlers* ptr_;
};
-#ifdef __cplusplus
-
-namespace upb {
-
-/* Convenience macros for creating a Handler object that is wrapped with a
- * type-safe wrapper function that converts the "void*" parameters/returns
- * of the underlying C API into nice C++ function.
- *
- * Sample usage:
- * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
- * // do stuff ...
- * }
- *
- * // Handler that doesn't need any data bound to it.
- * void OnValue2(MyClosure* c, int32_t val) {
- * // do stuff ...
- * }
- *
- * // Handler that returns bool so it can return failure if necessary.
- * bool OnValue3(MyClosure* c, int32_t val) {
- * // do stuff ...
- * return ok;
- * }
- *
- * // Member function handler.
- * class MyClosure {
- * public:
- * void OnValue(int32_t val) {
- * // do stuff ...
- * }
- * };
- *
- * // Takes ownership of the MyHandlerData.
- * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
- * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
- * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
- * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
- */
-
-#ifdef UPB_CXX11
-
-/* In C++11, the "template" disambiguator can appear even outside templates,
- * so all calls can safely use this pair of macros. */
-
-#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
-
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+#endif /* __cplusplus */
-#else
+/* upb_handlercache ***********************************************************/
-/* Prior to C++11, the "template" disambiguator may only appear inside a
- * template, so the regular macro must not use "template" */
+/* A upb_handlercache lazily builds and caches upb_handlers. You pass it a
+ * function (with optional closure) that can build handlers for a given
+ * message on-demand, and the cache maintains a map of msgdef->handlers. */
-#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc<f>()
+#ifdef __cplusplus
+extern "C" {
+#endif
-#define UpbBind(f, d) upb::MatchFunc(f).GetFunc<f>((d))
+struct upb_handlercache;
+typedef struct upb_handlercache upb_handlercache;
-#endif /* UPB_CXX11 */
+typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
-/* This macro must be used in C++98 for calls from inside a template. But we
- * define this variant in all cases; code that wants to be compatible with both
- * C++98 and C++11 should always use this macro when calling from a template. */
-#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc<f>()
+upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
+ const void *closure);
+void upb_handlercache_free(upb_handlercache *cache);
+const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
+ const upb_msgdef *md);
+bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
+ upb_handlerfree *hfree);
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
+#ifdef __cplusplus
+} /* extern "C" */
-/* Handler: a struct that contains the (handler, data, deleter) tuple that is
- * used to register all handlers. Users can Make() these directly but it's
- * more convenient to use the UpbMakeHandler/UpbBind macros above. */
-template <class T> class Handler {
+class upb::HandlerCache {
public:
- /* The underlying, handler function signature that upb uses internally. */
- typedef T FuncPtr;
+ HandlerCache(upb_handlers_callback *callback, const void *closure)
+ : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {}
+ HandlerCache(HandlerCache&&) = default;
+ HandlerCache& operator=(HandlerCache&&) = default;
+ HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {}
- /* Intentionally implicit. */
- template <class F> Handler(F func);
- ~Handler();
+ upb_handlercache* ptr() { return ptr_.get(); }
- private:
- void AddCleanup(Handlers* h) const {
- if (cleanup_func_) {
- bool ok = h->AddCleanup(cleanup_data_, cleanup_func_);
- UPB_ASSERT(ok);
- }
+ const upb_handlers *Get(MessageDefPtr md) {
+ return upb_handlercache_get(ptr_.get(), md.ptr());
}
- UPB_DISALLOW_COPY_AND_ASSIGN(Handler)
- friend class Handlers;
- FuncPtr handler_;
- mutable HandlerAttributes attr_;
- mutable bool registered_;
- void *cleanup_data_;
- upb_handlerfree *cleanup_func_;
+ private:
+ std::unique_ptr<upb_handlercache, decltype(&upb_handlercache_free)> ptr_;
};
-} /* namespace upb */
-
#endif /* __cplusplus */
-UPB_BEGIN_EXTERN_C
-
-/* Native C API. */
-
-/* Handler function typedefs. */
-typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
- size_t n);
-typedef bool upb_startmsg_handlerfunc(void *c, const void*);
-typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
-typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
-typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
-typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
-typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
-typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
-typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
-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, 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, const void *hd);
-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_;
-}
+/* upb_byteshandler ***********************************************************/
-/* upb_handlers */
-typedef void upb_handlers_callback(const 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,
- const void *closure);
-
-/* Include refcounted methods like upb_handlers_ref(). */
-UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast)
-
-const upb_status *upb_handlers_status(upb_handlers *h);
-void upb_handlers_clearerr(upb_handlers *h);
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
- upb_handlerattr *attr);
+typedef struct {
+ upb_func *func;
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
- upb_int32_handlerfunc *func, upb_handlerattr *attr);
-bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
- upb_int64_handlerfunc *func, upb_handlerattr *attr);
-bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
- upb_uint32_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
- upb_uint64_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
- upb_float_handlerfunc *func, upb_handlerattr *attr);
-bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
- upb_double_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
- upb_bool_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
- upb_startstr_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
- upb_string_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
- upb_startfield_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
- upb_startfield_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- upb_handlerattr *attr);
-bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
- upb_endfield_handlerfunc *func,
- upb_handlerattr *attr);
+ /* 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;
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
- const upb_handlers *sub);
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
- const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
- upb_selector_t sel);
+#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT}
-UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h,
- upb_selector_t s) {
- return (upb_func *)h->table[s].func;
-}
+typedef struct {
+ upb_handlers_tabent table[3];
+} upb_byteshandler;
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
- upb_handlerattr *attr);
+#define UPB_BYTESHANDLER_INIT \
+ { \
+ { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \
+ }
-UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h,
- upb_selector_t s) {
- return upb_handlerattr_handlerdata(&h->table[s].attr);
+UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
+ upb_byteshandler init = UPB_BYTESHANDLER_INIT;
+ *handler = init;
}
#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. */
-class upb::BytesHandler {
- public:
- BytesHandler();
- ~BytesHandler();
-#else
-struct upb_byteshandler {
+extern "C" {
#endif
- upb_handlers_tabent table[3];
-};
-void upb_byteshandler_init(upb_byteshandler *h);
-
-/* Caller must ensure that "d" outlives the handlers.
- * TODO(haberman): should this have a "freeze" operation? It's not necessary
- * for memory management, but could be useful to force immutability and provide
- * a convenient moment to verify that all registration succeeded. */
+/* Caller must ensure that "d" outlives the handlers. */
bool upb_byteshandler_setstartstr(upb_byteshandler *h,
upb_startstr_handlerfunc *func, void *d);
bool upb_byteshandler_setstring(upb_byteshandler *h,
@@ -786,22 +684,20 @@ bool upb_byteshandler_setstring(upb_byteshandler *h,
bool upb_byteshandler_setendstr(upb_byteshandler *h,
upb_endfield_handlerfunc *func, void *d);
-/* "Static" methods */
-bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s);
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
- upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
- return start + 1;
-}
-
-/* Internal-only. */
-uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
-uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
+#ifdef __cplusplus
+} /* extern "C" */
+namespace upb {
+typedef upb_byteshandler BytesHandler;
+}
+#endif
/** Message handlers ******************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
* They write scalar data to a known offset from the message pointer.
*
@@ -827,7 +723,9 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-UPB_END_EXTERN_C
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
#include "upb/handlers-inl.h"
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback