Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.9 KiB
199 lines
6.9 KiB
/* |
|
* 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_ */
|
|
|