summaryrefslogtreecommitdiff
path: root/upb/table.int.h
diff options
context:
space:
mode:
Diffstat (limited to 'upb/table.int.h')
-rw-r--r--upb/table.int.h71
1 files changed, 43 insertions, 28 deletions
diff --git a/upb/table.int.h b/upb/table.int.h
index e27fb01..b6e8eb7 100644
--- a/upb/table.int.h
+++ b/upb/table.int.h
@@ -152,33 +152,50 @@ FUNCS(fptr, fptr, upb_func*, UPB_CTYPE_FPTR);
/* upb_table ******************************************************************/
-typedef union {
- uintptr_t num;
- struct {
- // We own this. NULL-terminated but may also contain binary data; see
- // explicit length below.
- // TODO: move the length to the start of the string in order to reduce
- // tabkey's size (to one machine word) in a way that supports static
- // initialization.
- const char *str;
- size_t length;
- } s;
-} upb_tabkey;
-
-#define UPB_TABKEY_NUM(n) {n}
-#ifdef UPB_C99
-// Given that |s| is a string literal, sizeof(s) gives us a
-// compile-time-constant strlen(). We must ensure that this works for static
-// data initializers.
-#define UPB_TABKEY_STR(strval) { .s = { .str = strval, \
- .length = sizeof(strval) - 1 } }
+#define UPB_TABKEY_NUM(n) n
+#define UPB_TABKEY_NONE 0
+// The preprocessor isn't quite powerful enough to turn the compile-time string
+// length into a byte-wise string representation, so code generation needs to
+// help it along.
+//
+// "len1" is the low byte and len4 is the high byte.
+#ifdef UPB_BIG_ENDIAN
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+ (uintptr_t)(len4 len3 len2 len1 strval)
+#else
+#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
+ (uintptr_t)(len1 len2 len3 len4 strval)
#endif
-// TODO(haberman): C++
-#define UPB_TABKEY_NONE {0}
+
+// Either:
+// 1. an actual integer key, or
+// 2. a pointer to a string prefixed by its uint32_t length, owned by us.
+//
+// ...depending on whether this is a string table or an int table. We would
+// make this a union of those two types, but C89 doesn't support statically
+// initializing a non-first union member.
+typedef uintptr_t upb_tabkey;
+
+// Ideally we could use a structure like this instead of the memcpy() calls:
+//
+// typedef struct {
+// uint32_t len;
+// char data[1]; // Allocate to correct length.
+// } upb_tabstr;
+//
+// But unfortuantely in C89 there is no way to statically initialize such a
+// thing. So instead of memcpy() the length in and out of the string.
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+ char* mem = (char*)key;
+ if (len) memcpy(len, mem, sizeof(*len));
+ return mem + sizeof(*len);
+}
typedef struct _upb_tabent {
upb_tabkey key;
_upb_value val;
+
// Internal chaining. This is const so we can create static initializers for
// tables. We cast away const sometimes, but *only* when the containing
// upb_table is known to be non-const. This requires a bit of care, but
@@ -235,16 +252,14 @@ UPB_INLINE size_t upb_table_size(const upb_table *t) {
// Internal-only functions, in .h file only out of necessity.
UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
- return e->key.num == 0;
+ return e->key == 0;
}
// Used by some of the unit tests for generic hashing functionality.
uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed);
-UPB_INLINE upb_tabkey upb_intkey(uintptr_t key) {
- upb_tabkey k;
- k.num = key;
- return k;
+UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
+ return key;
}
UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
@@ -350,7 +365,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
const upb_tabent *e;
if (t->t.entries == NULL) return false;
for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
- if ((uint32_t)e->key.num == key) {
+ if ((uint32_t)e->key == key) {
_upb_value_setval(v, e->val, t->t.ctype);
return true;
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback