summaryrefslogtreecommitdiff
path: root/upb/shim
diff options
context:
space:
mode:
authorJosh Haberman <haberman@google.com>2013-05-25 10:26:59 -0700
committerJosh Haberman <haberman@google.com>2013-05-25 10:26:59 -0700
commit90bb4246c34580eb6c8a5a41a4e19fcd5f334f09 (patch)
treec0a5fedd4633dcaf1e975adc2edb34332a5dd686 /upb/shim
parentcfdb9907cb87d15eaab72ceefbfa42fd7a4c3127 (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.c69
-rw-r--r--upb/shim/shim.h74
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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback