|
|
|
/*
|
|
|
|
* Copyright (c) 2009-2021, Google LLC
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* * Neither the name of Google LLC nor the
|
|
|
|
* names of its contributors may be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* upb_table
|
|
|
|
*
|
|
|
|
* This header is INTERNAL-ONLY! Its interfaces are not public or stable!
|
|
|
|
* This file defines very fast int->upb_value (inttable) and string->upb_value
|
|
|
|
* (strtable) hash tables.
|
|
|
|
*
|
|
|
|
* The table uses chained scatter with Brent's variation (inspired by the Lua
|
|
|
|
* implementation of hash tables). The hash function for strings is Austin
|
|
|
|
* Appleby's "MurmurHash."
|
|
|
|
*
|
|
|
|
* The inttable uses uintptr_t as its key, which guarantees it can be used to
|
|
|
|
* store pointers or integers of at least 32 bits (upb isn't really useful on
|
|
|
|
* systems where sizeof(void*) < 4).
|
|
|
|
*
|
|
|
|
* The table must be homogeneous (all values of the same type). In debug
|
|
|
|
* mode, we check this on insert and lookup.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef UPB_HASH_COMMON_H_
|
|
|
|
#define UPB_HASH_COMMON_H_
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "upb/base/string_view.h"
|
|
|
|
#include "upb/mem/arena.h"
|
|
|
|
|
|
|
|
// Must be last.
|
|
|
|
#include "upb/port/def.inc"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* upb_value ******************************************************************/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
uint64_t val;
|
|
|
|
} upb_value;
|
|
|
|
|
|
|
|
/* Variant that works with a length-delimited rather than NULL-delimited string,
|
|
|
|
* as supported by strtable. */
|
|
|
|
char* upb_strdup2(const char* s, size_t len, upb_Arena* a);
|
|
|
|
|
|
|
|
UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; }
|
|
|
|
|
|
|
|
/* For each value ctype, define the following set of functions:
|
|
|
|
*
|
|
|
|
* // Get/set an int32 from a upb_value.
|
|
|
|
* int32_t upb_value_getint32(upb_value val);
|
|
|
|
* void upb_value_setint32(upb_value *val, int32_t cval);
|
|
|
|
*
|
|
|
|
* // Construct a new upb_value from an int32.
|
|
|
|
* upb_value upb_value_int32(int32_t val); */
|
|
|
|
#define FUNCS(name, membername, type_t, converter, proto_type) \
|
|
|
|
UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \
|
|
|
|
val->val = (converter)cval; \
|
|
|
|
} \
|
|
|
|
UPB_INLINE upb_value upb_value_##name(type_t val) { \
|
|
|
|
upb_value ret; \
|
|
|
|
upb_value_set##name(&ret, val); \
|
|
|
|
return ret; \
|
|
|
|
} \
|
|
|
|
UPB_INLINE type_t upb_value_get##name(upb_value val) { \
|
|
|
|
return (type_t)(converter)val.val; \
|
|
|
|
}
|
|
|
|
|
|
|
|
FUNCS(int32, int32, int32_t, int32_t, UPB_CTYPE_INT32)
|
|
|
|
FUNCS(int64, int64, int64_t, int64_t, UPB_CTYPE_INT64)
|
|
|
|
FUNCS(uint32, uint32, uint32_t, uint32_t, UPB_CTYPE_UINT32)
|
|
|
|
FUNCS(uint64, uint64, uint64_t, uint64_t, UPB_CTYPE_UINT64)
|
|
|
|
FUNCS(bool, _bool, bool, bool, UPB_CTYPE_BOOL)
|
|
|
|
FUNCS(cstr, cstr, char*, uintptr_t, UPB_CTYPE_CSTR)
|
|
|
|
FUNCS(ptr, ptr, void*, uintptr_t, UPB_CTYPE_PTR)
|
|
|
|
FUNCS(constptr, constptr, const void*, uintptr_t, UPB_CTYPE_CONSTPTR)
|
|
|
|
|
|
|
|
#undef FUNCS
|
|
|
|
|
|
|
|
UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) {
|
|
|
|
memcpy(&val->val, &cval, sizeof(cval));
|
|
|
|
}
|
|
|
|
|
|
|
|
UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) {
|
|
|
|
memcpy(&val->val, &cval, sizeof(cval));
|
|
|
|
}
|
|
|
|
|
|
|
|
UPB_INLINE upb_value upb_value_float(float cval) {
|
|
|
|
upb_value ret;
|
|
|
|
upb_value_setfloat(&ret, cval);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
UPB_INLINE upb_value upb_value_double(double cval) {
|
|
|
|
upb_value ret;
|
|
|
|
upb_value_setdouble(&ret, cval);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef SET_TYPE
|
|
|
|
|
|
|
|
/* upb_tabkey *****************************************************************/
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) {
|
|
|
|
upb_StringView ret;
|
|
|
|
uint32_t len;
|
|
|
|
ret.data = upb_tabstr(key, &len);
|
|
|
|
ret.size = len;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* upb_tabval *****************************************************************/
|
|
|
|
|
|
|
|
typedef struct upb_tabval {
|
|
|
|
uint64_t val;
|
|
|
|
} upb_tabval;
|
|
|
|
|
|
|
|
#define UPB_TABVALUE_EMPTY_INIT \
|
|
|
|
{ -1 }
|
|
|
|
|
|
|
|
/* upb_table ******************************************************************/
|
|
|
|
|
|
|
|
typedef struct _upb_tabent {
|
|
|
|
upb_tabkey key;
|
|
|
|
upb_tabval 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
|
|
|
|
* the subtlety is confined to table.c. */
|
|
|
|
const struct _upb_tabent* next;
|
|
|
|
} upb_tabent;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
size_t count; /* Number of entries in the hash part. */
|
|
|
|
uint32_t mask; /* Mask to turn hash value -> bucket. */
|
|
|
|
uint32_t max_count; /* Max count before we hit our load limit. */
|
|
|
|
uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */
|
|
|
|
upb_tabent* entries;
|
|
|
|
} upb_table;
|
|
|
|
|
|
|
|
UPB_INLINE size_t upb_table_size(const upb_table* t) {
|
|
|
|
return t->size_lg2 ? 1 << t->size_lg2 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Internal-only functions, in .h file only out of necessity.
|
|
|
|
|
|
|
|
UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; }
|
|
|
|
|
|
|
|
uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} /* extern "C" */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "upb/port/undef.inc"
|
|
|
|
|
|
|
|
#endif /* UPB_HASH_COMMON_H_ */
|