|
|
|
@ -24,21 +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_TYPE(upb::Handlers, upb_handlers) |
|
|
|
|
UPB_DECLARE_TYPE(upb::HandlerCache, upb_handlercache) |
|
|
|
|
|
|
|
|
|
/* 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. |
|
|
|
@ -80,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 |
|
|
|
@ -113,126 +83,234 @@ 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; |
|
|
|
|
|
|
|
|
|
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 { |
|
|
|
|
const T *GetAttachedObject() const { |
|
|
|
|
return objtype == UniquePtrForType<T>() ? static_cast<const T *>(obj) |
|
|
|
|
: NULL; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
const char *buf_; |
|
|
|
|
const void *obj_; |
|
|
|
|
const void *objtype_; |
|
|
|
|
size_t objofs_; |
|
|
|
|
}; |
|
|
|
|
} 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; |
|
|
|
|
|
|
|
|
|
UPB_BEGIN_EXTERN_C |
|
|
|
|
|
|
|
|
|
/* 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); |
|
|
|
|
|
|
|
|
|
UPB_END_EXTERN_C |
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
|
|
|
|
|
|
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: |
|
|
|
|
UPB_DISALLOW_COPY_AND_ASSIGN(Handler) |
|
|
|
|
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 |
|
|
|
|
* table with functions corresponding to all the events that can fire while |
|
|
|
@ -244,18 +322,23 @@ 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 *, 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; |
|
|
|
@ -275,21 +358,17 @@ class upb::Handlers { |
|
|
|
|
|
|
|
|
|
typedef void HandlersCallback(const void *closure, upb_handlers *h); |
|
|
|
|
|
|
|
|
|
/* 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(); |
|
|
|
|
|
|
|
|
|
/* 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:
|
|
|
|
|
* |
|
|
|
@ -299,7 +378,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:
|
|
|
|
|
* |
|
|
|
@ -309,7 +391,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 |
|
|
|
@ -331,13 +416,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 |
|
|
|
@ -345,8 +457,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:
|
|
|
|
|
* |
|
|
|
@ -384,9 +496,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:
|
|
|
|
|
* |
|
|
|
@ -402,7 +525,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: |
|
|
|
@ -419,7 +545,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: |
|
|
|
@ -432,7 +561,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: |
|
|
|
@ -445,328 +577,93 @@ 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); |
|
|
|
|
|
|
|
|
|
/* Gets the object that specifies handlers for the given field, which
|
|
|
|
|
* must be a submessage or group. Returns NULL if no handlers are set. */ |
|
|
|
|
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_handlercache *cache; |
|
|
|
|
const upb_msgdef *msg; |
|
|
|
|
const upb_handlers **sub; |
|
|
|
|
const void *top_closure_type; |
|
|
|
|
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" */ |
|
|
|
|
UPB_BEGIN_EXTERN_C |
|
|
|
|
|
|
|
|
|
#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc<f>() |
|
|
|
|
struct upb_handlercache; |
|
|
|
|
typedef struct upb_handlercache upb_handlercache; |
|
|
|
|
|
|
|
|
|
#define UpbBind(f, d) upb::MatchFunc(f).GetFunc<f>((d)) |
|
|
|
|
typedef void upb_handlers_callback(const void *closure, upb_handlers *h); |
|
|
|
|
|
|
|
|
|
#endif /* UPB_CXX11 */ |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
/* 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_END_EXTERN_C |
|
|
|
|
|
|
|
|
|
/* We have to be careful to only evaluate "d" once. */ |
|
|
|
|
#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc<f>((d)) |
|
|
|
|
#ifdef __cplusplus |
|
|
|
|
|
|
|
|
|
/* 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. */ |
|
|
|
|
/* upb_byteshandler ***********************************************************/ |
|
|
|
|
|
|
|
|
|
/* 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_BEGIN_EXTERN_C |
|
|
|
|
|
|
|
|
|
/* upb_handlers */ |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef void upb_handlers_callback(const void *closure, upb_handlers *h); |
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|
|
|
|
|
|
|
class upb::HandlerCache { |
|
|
|
|
public: |
|
|
|
|
static HandlerCache *New(upb_handlers_callback *callback, |
|
|
|
|
const void *closure); |
|
|
|
|
static void Free(HandlerCache* cache); |
|
|
|
|
|
|
|
|
|
const Handlers* Get(const MessageDef* md); |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
UPB_DISALLOW_POD_OPS(HandlerCache, upb::pb::HandlerCache) |
|
|
|
|
#else |
|
|
|
|
struct upb_handlercache { |
|
|
|
|
#endif |
|
|
|
|
upb_arena arena; |
|
|
|
|
upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ |
|
|
|
|
upb_inttable cleanup_; |
|
|
|
|
upb_handlers_callback *callback; |
|
|
|
|
const void *closure; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
#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 { |
|
|
|
|
#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, |
|
|
|
@ -774,21 +671,18 @@ bool upb_byteshandler_setstring(upb_byteshandler *h, |
|
|
|
|
bool upb_byteshandler_setendstr(upb_byteshandler *h, |
|
|
|
|
upb_endfield_handlerfunc *func, void *d); |
|
|
|
|
|
|
|
|
|
/* "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; |
|
|
|
|
#ifdef __cplusplus |
|
|
|
|
namespace upb { |
|
|
|
|
typedef upb_byteshandler BytesHandler; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* Internal-only. */ |
|
|
|
|
uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); |
|
|
|
|
uint32_t upb_handlers_selectorcount(const upb_fielddef *f); |
|
|
|
|
|
|
|
|
|
UPB_END_EXTERN_C |
|
|
|
|
|
|
|
|
|
/** Message handlers ******************************************************************/ |
|
|
|
|
|
|
|
|
|
UPB_BEGIN_EXTERN_C |
|
|
|
|
|
|
|
|
|
/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
|
|
|
|
|
* They write scalar data to a known offset from the message pointer. |
|
|
|
|
* |
|
|
|
|