C++ handlers are now type-safe; SinkFrame is gone. Various other changes.pull/13171/head
parent
cfdb9907cb
commit
90bb4246c3
26 changed files with 1942 additions and 1861 deletions
@ -0,0 +1,470 @@ |
||||
/*
|
||||
* upb - a minimalist implementation of protocol buffers. |
||||
* |
||||
* Copyright (c) 2011-2012 Google Inc. See LICENSE for details. |
||||
* Author: Josh Haberman <jhaberman@gmail.com> |
||||
* |
||||
* Inline definitions for handlers.h, which are particularly long and a bit |
||||
* tricky. |
||||
*/ |
||||
|
||||
#ifndef UPB_HANDLERS_INL_H_ |
||||
#define UPB_HANDLERS_INL_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
|
||||
namespace upb { |
||||
|
||||
// Deleter: class for constructing a function that deletes a pointer type.
|
||||
template <class T> struct Deleter { |
||||
static void Delete(void* p) { delete static_cast<T*>(p); } |
||||
}; |
||||
|
||||
template <class T> Deleter<T> MatchDeleter(T* data) { |
||||
UPB_UNUSED(data); |
||||
return Deleter<T>(); |
||||
} |
||||
|
||||
// Template magic for creating type-safe wrappers around the user's actual
|
||||
// function. These convert between the void*'s of the C API and the C++
|
||||
// user's types. These also handle conversion between multiple types with
|
||||
// the same witdh; ie "long long" and "long" are both 64 bits on LP64.
|
||||
|
||||
// ValueHandler
|
||||
template <class C, class T1, class T2 = typename CanonicalType<T1>::Type> |
||||
struct ValueHandlerWrapper2 { |
||||
template <bool F(C *, T1)> |
||||
inline static bool Wrapper(void *closure, const void *hd, T2 val) { |
||||
UPB_UNUSED(hd); |
||||
return F(static_cast<C *>(closure), val); |
||||
} |
||||
}; |
||||
|
||||
template <class C, class D, class T1, |
||||
class T2 = typename CanonicalType<T1>::Type> |
||||
struct ValueHandlerWrapper3 { |
||||
template <bool F(C *, const D *, T1)> |
||||
inline static bool Wrapper(void *closure, const void *hd, T2 val) { |
||||
return F(static_cast<C *>(closure), static_cast<const D *>(hd), val); |
||||
} |
||||
}; |
||||
|
||||
template <class C, class T> |
||||
inline ValueHandlerWrapper2<C, T> MatchWrapper(bool (*f)(C *, T)) { |
||||
UPB_UNUSED(f); |
||||
return ValueHandlerWrapper2<C, T>(); |
||||
} |
||||
|
||||
template <class C, class D, class T> |
||||
inline ValueHandlerWrapper3<C, D, T> MatchWrapper(bool (*f)(C *, const D *, |
||||
T)) { |
||||
UPB_UNUSED(f); |
||||
return ValueHandlerWrapper3<C, D, T>(); |
||||
} |
||||
|
||||
template <class T> |
||||
inline typename ValueHandler<T>::H MakeHandler(bool (*wrapper)(void *, |
||||
const void *, |
||||
T)) { |
||||
return ValueHandler<T>::H::Make(wrapper, NULL, NULL); |
||||
} |
||||
|
||||
template <class C, class D, class T1, class T2> |
||||
inline typename ValueHandler<T1>::H BindHandler( |
||||
bool (*wrapper)(void *, const void *, T1), bool (*h)(C *, const D *, T2), |
||||
D *data) { |
||||
UPB_UNUSED(h); // Only for making sure function matches "D".
|
||||
return ValueHandler<T1>::H::Make(wrapper, data, MatchDeleter(data).Delete); |
||||
} |
||||
|
||||
// StartFieldHandler
|
||||
template <class R, class C> struct StartFieldHandlerWrapper2 { |
||||
template <R *F(C *)> static void *Wrapper(void *closure, const void *hd) { |
||||
UPB_UNUSED(hd); |
||||
return F(static_cast<C *>(closure)); |
||||
} |
||||
}; |
||||
|
||||
template <class R, class C, class D> struct StartFieldHandlerWrapper3 { |
||||
template <R *F(C *, const D *)> |
||||
inline static void *Wrapper(void *closure, const void *hd) { |
||||
return F(static_cast<C *>(closure), static_cast<const D *>(hd)); |
||||
} |
||||
}; |
||||
|
||||
template <class R, class C> |
||||
inline StartFieldHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *)) { |
||||
UPB_UNUSED(f); |
||||
return StartFieldHandlerWrapper2<R, C>(); |
||||
} |
||||
|
||||
template <class R, class C, class D> |
||||
inline StartFieldHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *, |
||||
const D *)) { |
||||
UPB_UNUSED(f); |
||||
return StartFieldHandlerWrapper3<R, C, D>(); |
||||
} |
||||
|
||||
inline StartFieldHandler MakeHandler(void *(*wrapper)(void *, const void *)) { |
||||
return StartFieldHandler::Make(wrapper, NULL, NULL); |
||||
} |
||||
|
||||
template <class R, class C, class D> |
||||
inline StartFieldHandler BindHandler(void *(*wrapper)(void *, const void *), |
||||
R *(*h)(C *, const D *), D *data) { |
||||
UPB_UNUSED(h); // Only for making sure function matches "D".
|
||||
return StartFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete); |
||||
} |
||||
|
||||
// EndFieldHandler
|
||||
template <class C> struct EndFieldHandlerWrapper2 { |
||||
template <bool F(C *)> |
||||
inline static bool Wrapper(void *closure, const void *hd) { |
||||
UPB_UNUSED(hd); |
||||
return F(static_cast<C *>(closure)); |
||||
} |
||||
}; |
||||
|
||||
template <class C, class D> struct EndFieldHandlerWrapper3 { |
||||
template <bool F(C *, const D *)> |
||||
inline static bool Wrapper(void *closure, const void *hd) { |
||||
return F(static_cast<C *>(closure), static_cast<const D *>(hd)); |
||||
} |
||||
}; |
||||
|
||||
template <class C> |
||||
inline EndFieldHandlerWrapper2<C> MatchWrapper(bool (*f)(C *)) { |
||||
UPB_UNUSED(f); |
||||
return EndFieldHandlerWrapper2<C>(); |
||||
} |
||||
|
||||
template <class C, class D> |
||||
inline EndFieldHandlerWrapper3<C, D> MatchWrapper(bool (*f)(C *, const D *)) { |
||||
UPB_UNUSED(f); |
||||
return EndFieldHandlerWrapper3<C, D>(); |
||||
} |
||||
|
||||
inline EndFieldHandler MakeHandler(bool (*wrapper)(void *, const void *)) { |
||||
return EndFieldHandler::Make(wrapper, NULL, NULL); |
||||
} |
||||
|
||||
template <class C, class D> |
||||
inline EndFieldHandler BindHandler(bool (*wrapper)(void *, const void *), |
||||
bool (*h)(C *, const D *), D *data) { |
||||
UPB_UNUSED(h); // Only for making sure function matches "D".
|
||||
return EndFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete); |
||||
} |
||||
|
||||
// StartStringHandler
|
||||
template <class R, class C> struct StartStringHandlerWrapper2 { |
||||
template <R *F(C *, size_t)> |
||||
inline static void *Wrapper(void *closure, const void *hd, size_t hint) { |
||||
UPB_UNUSED(hd); |
||||
return F(static_cast<C *>(closure), hint); |
||||
} |
||||
}; |
||||
|
||||
template <class R, class C, class D> struct StartStringHandlerWrapper3 { |
||||
template <R *F(C *, const D *, size_t)> |
||||
inline static void *Wrapper(void *closure, const void *hd, size_t hint) { |
||||
return F(static_cast<C *>(closure), static_cast<const D *>(hd), hint); |
||||
} |
||||
}; |
||||
|
||||
template <class R, class C> |
||||
inline StartStringHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *, size_t)) { |
||||
UPB_UNUSED(f); |
||||
return StartStringHandlerWrapper2<R, C>(); |
||||
} |
||||
|
||||
template <class R, class C, class D> |
||||
inline StartStringHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *, const D *, |
||||
size_t)) { |
||||
UPB_UNUSED(f); |
||||
return StartStringHandlerWrapper3<R, C, D>(); |
||||
} |
||||
|
||||
inline StartStringHandler MakeHandler(void *(*wrapper)(void *, const void *, |
||||
size_t)) { |
||||
return StartStringHandler::Make(wrapper, NULL, NULL); |
||||
} |
||||
|
||||
template <class R, class C, class D> |
||||
inline StartStringHandler BindHandler(void *(*wrapper)(void *, const void *, |
||||
size_t), |
||||
R *(*h)(C *, const D *, size_t), |
||||
D *data) { |
||||
UPB_UNUSED(h); // Only for making sure function matches "D".
|
||||
return StartStringHandler::Make(wrapper, data, MatchDeleter(data).Delete); |
||||
} |
||||
|
||||
// StringHandler
|
||||
template <class C> struct StringHandlerWrapper2 { |
||||
template <size_t F(C *, const char *buf, size_t len)> |
||||
inline static size_t Wrapper(void *closure, const void *hd, const char *buf, |
||||
size_t len) { |
||||
UPB_UNUSED(hd); |
||||
return F(static_cast<C *>(closure), buf, len); |
||||
} |
||||
}; |
||||
|
||||
template <class C, class D> struct StringHandlerWrapper3 { |
||||
template <size_t F(C *, const D *, const char *buf, size_t len)> |
||||
inline static size_t Wrapper(void *closure, const void *hd, const char *buf, |
||||
size_t len) { |
||||
return F(static_cast<C *>(closure), static_cast<const D *>(hd), buf, len); |
||||
} |
||||
}; |
||||
|
||||
template <class C> |
||||
inline StringHandlerWrapper2<C> MatchWrapper(size_t (*f)(C *, const char *, |
||||
size_t)) { |
||||
UPB_UNUSED(f); |
||||
return StringHandlerWrapper2<C>(); |
||||
} |
||||
|
||||
template <class C, class D> |
||||
inline StringHandlerWrapper3<C, D> MatchWrapper(size_t (*f)(C *, const D *, |
||||
const char *, |
||||
size_t)) { |
||||
UPB_UNUSED(f); |
||||
return StringHandlerWrapper3<C, D>(); |
||||
} |
||||
|
||||
inline StringHandler MakeHandler(size_t (*wrapper)(void *, const void *, |
||||
const char *, size_t)) { |
||||
return StringHandler::Make(wrapper, NULL, NULL); |
||||
} |
||||
|
||||
template <class C, class D> |
||||
inline StringHandler BindHandler( |
||||
size_t (*wrapper)(void *, const void *, const char *, size_t), |
||||
size_t (*h)(C *, const D *, const char *, size_t), D *data) { |
||||
UPB_UNUSED(h); // Only for making sure function matches "D".
|
||||
return StringHandler::Make(wrapper, data, MatchDeleter(data).Delete); |
||||
} |
||||
|
||||
// utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
|
||||
// variant C type.
|
||||
#define TYPE_METHODS(utype, ltype, ctype, vtype) \ |
||||
template <> struct CanonicalType<vtype> { \
|
||||
typedef ctype Type; \
|
||||
}; \
|
||||
template <> \
|
||||
inline bool Handlers::SetValueHandler<vtype>( \
|
||||
const FieldDef *f, \
|
||||
const typename ValueHandler<typename CanonicalType<vtype>::Type>::H & \
|
||||
handler) { \
|
||||
handler.registered_ = true; \
|
||||
return upb_handlers_set##ltype(this, f, handler.handler_, handler.data_, \
|
||||
handler.cleanup_); \
|
||||
} \
|
||||
template <> \
|
||||
inline bool Handlers::SetValueHandler<vtype>( \
|
||||
const char *f, const typename ValueHandler< \
|
||||
typename CanonicalType<vtype>::Type>::H &handler) { \
|
||||
handler.registered_ = true; \
|
||||
return upb_handlers_set##ltype##_n(this, f, handler.handler_, \
|
||||
handler.data_, handler.cleanup_); \
|
||||
} |
||||
|
||||
TYPE_METHODS(Double, double, double, double); |
||||
TYPE_METHODS(Float, float, float, float); |
||||
TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64_t); |
||||
TYPE_METHODS(UInt32, uint32, uint32_t, upb_uint32_t); |
||||
TYPE_METHODS(Int64, int64, int64_t, upb_int64_t); |
||||
TYPE_METHODS(Int32, int32, int32_t, upb_int32_t); |
||||
TYPE_METHODS(Bool, bool, bool, bool); |
||||
|
||||
#ifdef UPB_TWO_32BIT_TYPES |
||||
TYPE_METHODS(Int32, int32, int32_t, upb_int32alt_t); |
||||
TYPE_METHODS(Uint32, uint32, uint32_t, upb_uint32alt_t); |
||||
#endif |
||||
|
||||
#ifdef UPB_TWO_64BIT_TYPES |
||||
TYPE_METHODS(Int64, int64, int64_t, upb_int64alt_t); |
||||
TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64alt_t); |
||||
#endif |
||||
#undef TYPE_METHODS |
||||
|
||||
// Type methods that are only one-per-canonical-type and not one-per-cvariant.
|
||||
|
||||
#define TYPE_METHODS(utype, ctype) \ |
||||
inline bool Handlers::Set##utype##Handler(const FieldDef *f, \
|
||||
const utype##Handler &h) { \
|
||||
return SetValueHandler<ctype>(f, h); \
|
||||
} \
|
||||
inline bool Handlers::Set##utype##Handler(const char *f, \
|
||||
const utype##Handler &h) { \
|
||||
return SetValueHandler<ctype>(f, h); \
|
||||
} |
||||
|
||||
TYPE_METHODS(Double, double); |
||||
TYPE_METHODS(Float, float); |
||||
TYPE_METHODS(UInt64, uint64_t); |
||||
TYPE_METHODS(UInt32, uint32_t); |
||||
TYPE_METHODS(Int64, int64_t); |
||||
TYPE_METHODS(Int32, int32_t); |
||||
TYPE_METHODS(Bool, bool); |
||||
#undef TYPE_METHODS |
||||
|
||||
template <class T1, bool F(T1*)> bool Wrapper1(void *p1) { |
||||
return F(static_cast<T1*>(p1)); |
||||
} |
||||
template <class T1, bool F(T1 *, upb::Status *)> |
||||
bool EndMessageWrapper(void *p1, upb::Status *s) { |
||||
return F(static_cast<T1 *>(p1), s); |
||||
} |
||||
inline Handlers *Handlers::New(const MessageDef *m, const FrameType *ft, |
||||
const void *owner) { |
||||
return upb_handlers_new(m, ft, owner); |
||||
} |
||||
inline const Handlers *Handlers::NewFrozen(const MessageDef *m, |
||||
const FrameType *ft, |
||||
const void *owner, |
||||
upb_handlers_callback *callback, |
||||
void *closure) { |
||||
return upb_handlers_newfrozen(m, ft, owner, callback, closure); |
||||
} |
||||
inline bool Handlers::IsFrozen() const { return upb_handlers_isfrozen(this); } |
||||
inline void Handlers::Ref(const void *owner) const { |
||||
upb_handlers_ref(this, owner); |
||||
} |
||||
inline void Handlers::Unref(const void *owner) const { |
||||
upb_handlers_unref(this, owner); |
||||
} |
||||
inline void Handlers::DonateRef(const void *from, const void *to) const { |
||||
upb_handlers_donateref(this, from, to); |
||||
} |
||||
inline void Handlers::CheckRef(const void *owner) const { |
||||
upb_handlers_checkref(this, owner); |
||||
} |
||||
inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) { |
||||
return upb_handlers_freeze(handlers, n, s); |
||||
} |
||||
inline const FrameType *Handlers::frame_type() const { |
||||
return upb_handlers_frametype(this); |
||||
} |
||||
inline const MessageDef *Handlers::message_def() const { |
||||
return upb_handlers_msgdef(this); |
||||
} |
||||
template <class T, bool F(T *)> void Handlers::SetStartMessageHandler() { |
||||
upb_handlers_setstartmsg(this, &Wrapper1<T, F>); |
||||
} |
||||
template <class T, bool F(T *, upb::Status *)> |
||||
void Handlers::SetEndMessageHandler() { |
||||
upb_handlers_setendmsg(this, &EndMessageWrapper<T, F>); |
||||
} |
||||
inline bool Handlers::SetStartStringHandler(const FieldDef *f, |
||||
const StartStringHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartstr(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndStringHandler(const FieldDef *f, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendstr(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStringHandler(const FieldDef *f, |
||||
const StringHandler& handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstring(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStartSequenceHandler( |
||||
const FieldDef *f, const StartFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartseq(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStartSubMessageHandler( |
||||
const FieldDef *f, const StartFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartsubmsg(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendsubmsg(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendseq(this, f, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { |
||||
return upb_handlers_setsubhandlers(this, f, sub); |
||||
} |
||||
inline bool Handlers::SetStartStringHandler(const char *name, |
||||
const StartStringHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartstr_n(this, name, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndStringHandler(const char *name, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendstr_n(this, name, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStringHandler(const char *name, |
||||
const StringHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstring_n(this, name, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStartSequenceHandler( |
||||
const char *name, const StartFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartseq_n(this, name, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetStartSubMessageHandler( |
||||
const char *name, const StartFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setstartsubmsg_n(this, name, handler.handler_, |
||||
handler.data_, handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndSubMessageHandler(const char *name, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendsubmsg_n(this, name, handler.handler_, |
||||
handler.data_, handler.cleanup_); |
||||
} |
||||
inline bool Handlers::SetEndSequenceHandler(const char *name, |
||||
const EndFieldHandler &handler) { |
||||
handler.registered_ = true; |
||||
return upb_handlers_setendseq_n(this, name, handler.handler_, handler.data_, |
||||
handler.cleanup_); |
||||
} |
||||
inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { |
||||
return upb_handlers_getsubhandlers(this, f); |
||||
} |
||||
inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const { |
||||
return upb_handlers_getsubhandlers_sel(this, sel); |
||||
} |
||||
inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type, |
||||
Handlers::Selector *s) { |
||||
return upb_handlers_getselector(f, type, s); |
||||
} |
||||
inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { |
||||
return upb_handlers_getendselector(start); |
||||
} |
||||
inline Handlers::GenericFunction *Handlers::GetHandler( |
||||
Handlers::Selector selector) { |
||||
return upb_handlers_gethandler(this, selector); |
||||
} |
||||
inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { |
||||
return upb_handlers_gethandlerdata(this, selector); |
||||
} |
||||
|
||||
} // namespace upb
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // UPB_HANDLERS_INL_H_
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@ |
||||
/*
|
||||
* upb - a minimalist implementation of protocol buffers. |
||||
* |
||||
* Copyright (c) 2013 Google Inc. See LICENSE for details. |
||||
* Author: Josh Haberman <jhaberman@gmail.com> |
||||
*/ |
||||
|
||||
#include "upb/shim/shim.h" |
||||
|
||||
#include <stdlib.h> |
||||
|
||||
// Fallback implementation if the shim is not specialized by the JIT.
|
||||
#define SHIM_WRITER(type, ctype) \ |
||||
bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \
|
||||
uint8_t *m = c; \
|
||||
const upb_shim_data *d = hd; \
|
||||
if (d->hasbit > 0) \
|
||||
*(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \
|
||||
*(ctype*)&m[d->offset] = val; \
|
||||
return true; \
|
||||
} \
|
||||
|
||||
SHIM_WRITER(double, double) |
||||
SHIM_WRITER(float, float) |
||||
SHIM_WRITER(int32, int32_t) |
||||
SHIM_WRITER(int64, int64_t) |
||||
SHIM_WRITER(uint32, uint32_t) |
||||
SHIM_WRITER(uint64, uint64_t) |
||||
SHIM_WRITER(bool, bool) |
||||
#undef SHIM_WRITER |
||||
|
||||
bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, |
||||
int32_t hasbit) { |
||||
upb_shim_data *d = malloc(sizeof(*d)); |
||||
if (!d) return false; |
||||
d->offset = offset; |
||||
d->hasbit = hasbit; |
||||
|
||||
#define TYPE(u, l) \ |
||||
case UPB_TYPE_##u: return upb_handlers_set##l(h, f, upb_shim_set##l, d, free) |
||||
|
||||
switch (upb_fielddef_type(f)) { |
||||
TYPE(INT64, int64); |
||||
TYPE(INT32, int32); |
||||
TYPE(ENUM, int32); |
||||
TYPE(UINT64, uint64); |
||||
TYPE(UINT32, uint32); |
||||
TYPE(DOUBLE, double); |
||||
TYPE(FLOAT, float); |
||||
TYPE(BOOL, bool); |
||||
default: assert(false); return false; |
||||
} |
||||
#undef TYPE |
||||
} |
||||
|
||||
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s) { |
||||
upb_func *f = upb_handlers_gethandler(h, s); |
||||
if ((upb_int64_handler*)f == upb_shim_setint64 || |
||||
(upb_int32_handler*)f == upb_shim_setint32 || |
||||
(upb_uint64_handler*)f == upb_shim_setuint64 || |
||||
(upb_uint32_handler*)f == upb_shim_setuint32 || |
||||
(upb_double_handler*)f == upb_shim_setdouble || |
||||
(upb_float_handler*)f == upb_shim_setfloat || |
||||
(upb_bool_handler*)f == upb_shim_setbool) { |
||||
return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s); |
||||
} else { |
||||
return NULL; |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
/*
|
||||
* upb - a minimalist implementation of protocol buffers. |
||||
* |
||||
* Copyright (c) 2013 Google Inc. See LICENSE for details. |
||||
* Author: Josh Haberman <jhaberman@gmail.com> |
||||
* |
||||
* For handlers that do very tiny, very simple operations, the function call |
||||
* overhead of calling a handler can be significant. This file allows the |
||||
* user to define handlers that do something very simple like store the value |
||||
* to memory and/or set a hasbit. JIT compilers can then special-case these |
||||
* handlers and emit specialized code for them instead of actually calling the |
||||
* handler. |
||||
* |
||||
* The functionality is very simple/limited right now but may expand to be able |
||||
* to call another function. |
||||
*/ |
||||
|
||||
#ifndef UPB_SHIM_H |
||||
#define UPB_SHIM_H |
||||
|
||||
#include "upb/handlers.h" |
||||
|
||||
typedef struct { |
||||
size_t offset; |
||||
int32_t hasbit; |
||||
} upb_shim_data; |
||||
|
||||
#ifdef __cplusplus |
||||
|
||||
namespace upb { |
||||
|
||||
struct Shim { |
||||
typedef upb_shim_data Data; |
||||
|
||||
// Sets a handler for the given field that writes the value to the given
|
||||
// offset and, if hasbit >= 0, sets a bit at the given bit offset. Returns
|
||||
// true if the handler was set successfully.
|
||||
static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit); |
||||
|
||||
// If this handler is a shim, returns the corresponding upb::Shim::Data.
|
||||
// Otherwise returns NULL.
|
||||
static const Data* GetData(const Handlers* h, Handlers::Selector s); |
||||
}; |
||||
|
||||
} // namespace upb
|
||||
|
||||
extern "C" { |
||||
#endif |
||||
|
||||
// C API.
|
||||
bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, |
||||
int32_t hasbit); |
||||
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s); |
||||
|
||||
#ifdef __cplusplus |
||||
} // extern "C"
|
||||
|
||||
namespace upb { |
||||
|
||||
// C++ Wrappers.
|
||||
inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs, |
||||
int32_t hasbit) { |
||||
return upb_shim_set(h, f, ofs, hasbit); |
||||
} |
||||
inline const Shim::Data* Shim::GetData(const Handlers* h, |
||||
Handlers::Selector s) { |
||||
return upb_shim_getdata(h, s); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
#endif |
||||
|
||||
#endif // UPB_SHIM_H
|
Loading…
Reference in new issue