diff options
author | Josh Haberman <haberman@google.com> | 2013-05-25 10:26:59 -0700 |
---|---|---|
committer | Josh Haberman <haberman@google.com> | 2013-05-25 10:26:59 -0700 |
commit | 90bb4246c34580eb6c8a5a41a4e19fcd5f334f09 (patch) | |
tree | c0a5fedd4633dcaf1e975adc2edb34332a5dd686 /upb/shim | |
parent | cfdb9907cb87d15eaab72ceefbfa42fd7a4c3127 (diff) |
Synced with Google-internal development.
C++ handlers are now type-safe; SinkFrame is gone.
Various other changes.
Diffstat (limited to 'upb/shim')
-rw-r--r-- | upb/shim/shim.c | 69 | ||||
-rw-r--r-- | upb/shim/shim.h | 74 |
2 files changed, 143 insertions, 0 deletions
diff --git a/upb/shim/shim.c b/upb/shim/shim.c new file mode 100644 index 0000000..6a79ac0 --- /dev/null +++ b/upb/shim/shim.c @@ -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; + } +} diff --git a/upb/shim/shim.h b/upb/shim/shim.h new file mode 100644 index 0000000..98310d7 --- /dev/null +++ b/upb/shim/shim.h @@ -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 |