Auto-generate files after cl/594514934
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h
index 73437ce..59d543c 100755
--- a/ruby/ext/google/protobuf_c/ruby-upb.h
+++ b/ruby/ext/google/protobuf_c/ruby-upb.h
@@ -827,175 +827,571 @@
#include <stdint.h>
-#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_
-#define UPB_MINI_TABLE_TAGGED_PTR_H_
+#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_
+#define UPB_MESSAGE_INTERNAL_ARRAY_H_
-#include <stdint.h>
-
-
-#ifndef UPB_MESSAGE_TYPES_H_
-#define UPB_MESSAGE_TYPES_H_
-
-// This typedef is in a leaf header to resolve a circular dependency between
-// messages and mini tables.
-typedef struct upb_Message {
- int unused; // Placeholder cuz Windows won't compile an empty struct.
-} upb_Message;
-
-#endif /* UPB_MESSAGE_TYPES_H_ */
-
-// Must be last.
-
-// When a upb_Message* is stored in a message, array, or map, it is stored in a
-// tagged form. If the tag bit is set, the referenced upb_Message is of type
-// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of
-// that field's true message type. This forms the basis of what we call
-// "dynamic tree shaking."
-//
-// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for
-// more information.
-
-typedef uintptr_t upb_TaggedMessagePtr;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Internal-only because empty messages cannot be created by the user.
-UPB_INLINE upb_TaggedMessagePtr _upb_TaggedMessagePtr_Pack(upb_Message* ptr,
- bool empty) {
- UPB_ASSERT(((uintptr_t)ptr & 1) == 0);
- return (uintptr_t)ptr | (empty ? 1 : 0);
-}
-
-// Users who enable unlinked sub-messages must use this to test whether a
-// message is empty before accessing it. If a message is empty, it must be
-// first promoted using the interfaces in message/promote.h.
-UPB_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr) {
- return ptr & 1;
-}
-
-UPB_INLINE upb_Message* _upb_TaggedMessagePtr_GetMessage(
- upb_TaggedMessagePtr ptr) {
- return (upb_Message*)(ptr & ~(uintptr_t)1);
-}
-
-UPB_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage(
- upb_TaggedMessagePtr ptr) {
- UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(ptr));
- return _upb_TaggedMessagePtr_GetMessage(ptr);
-}
-
-UPB_INLINE upb_Message* _upb_TaggedMessagePtr_GetEmptyMessage(
- upb_TaggedMessagePtr ptr) {
- UPB_ASSERT(upb_TaggedMessagePtr_IsEmpty(ptr));
- return _upb_TaggedMessagePtr_GetMessage(ptr);
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */
-
-typedef union {
- bool bool_val;
- float float_val;
- double double_val;
- int32_t int32_val;
- int64_t int64_val;
- uint32_t uint32_val;
- uint64_t uint64_val;
- const struct upb_Array* array_val;
- const struct upb_Map* map_val;
- const struct upb_Message* msg_val;
- upb_StringView str_val;
-
- // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of
- // msg_val if unlinked sub-messages may possibly be in use. See the
- // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more
- // information.
- upb_TaggedMessagePtr tagged_msg_val;
-} upb_MessageValue;
-
-typedef union {
- struct upb_Array* array;
- struct upb_Map* map;
- struct upb_Message* msg;
-} upb_MutableMessageValue;
-
-#endif /* UPB_MESSAGE_VALUE_H_ */
-
-// Must be last.
-
-typedef struct upb_Array upb_Array;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Creates a new array on the given arena that holds elements of this type.
-UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
-
-// Returns the number of elements in the array.
-UPB_API size_t upb_Array_Size(const upb_Array* arr);
-
-// Returns the given element, which must be within the array's current size.
-UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i);
-
-// Sets the given element, which must be within the array's current size.
-UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val);
-
-// Appends an element to the array. Returns false on allocation failure.
-UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val,
- upb_Arena* arena);
-
-// Moves elements within the array using memmove().
-// Like memmove(), the source and destination elements may be overlapping.
-UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
- size_t count);
-
-// Inserts one or more empty elements into the array.
-// Existing elements are shifted right.
-// The new elements have undefined state and must be set with `upb_Array_Set()`.
-// REQUIRES: `i <= upb_Array_Size(arr)`
-UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
- upb_Arena* arena);
-
-// Deletes one or more elements from the array.
-// Existing elements are shifted left.
-// REQUIRES: `i + count <= upb_Array_Size(arr)`
-UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
-
-// Changes the size of a vector. New elements are initialized to NULL/0.
-// Returns false on allocation failure.
-UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena);
-
-// Returns pointer to array data.
-UPB_API const void* upb_Array_DataPtr(const upb_Array* arr);
-
-// Returns mutable pointer to array data.
-UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MESSAGE_ARRAY_H_ */
-
-#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_
-#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_
-
-#include <stddef.h>
-#include <stdint.h>
#include <string.h>
-#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
-#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
+// Must be last.
+#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit.
+#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size.
+#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// LINT.IfChange(struct_definition)
+// Our internal representation for repeated fields.
+struct upb_Array {
+ // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows:
+ // 0 maps to elem size 1
+ // 1 maps to elem size 4
+ // 2 maps to elem size 8
+ // 3 maps to elem size 16
+ //
+ // Bit #2 contains the frozen/immutable flag (currently unimplemented).
+ uintptr_t data;
+
+ size_t UPB_ONLYBITS(size); // The number of elements in the array.
+ size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements.
+};
+
+UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array,
+ void* data, size_t lg2) {
+ UPB_ASSERT(lg2 != 1);
+ UPB_ASSERT(lg2 <= 4);
+ const size_t bits = lg2 - (lg2 != 0);
+ array->data = (uintptr_t)data | bits;
+}
+
+UPB_INLINE size_t
+UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) {
+ const size_t bits = array->data & _UPB_ARRAY_MASK_LG2;
+ const size_t lg2 = bits + (bits != 0);
+ return lg2;
+}
+
+UPB_INLINE const void* _upb_array_constptr(const struct upb_Array* array) {
+ UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions.
+ return (void*)(array->data & ~(uintptr_t)_UPB_ARRAY_MASK_ALL);
+}
+
+UPB_INLINE void* _upb_array_ptr(struct upb_Array* array) {
+ return (void*)_upb_array_constptr(array);
+}
+
+UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena,
+ size_t init_capacity,
+ int elem_size_lg2) {
+ UPB_ASSERT(elem_size_lg2 != 1);
+ UPB_ASSERT(elem_size_lg2 <= 4);
+ const size_t array_size =
+ UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN);
+ const size_t bytes = array_size + (init_capacity << elem_size_lg2);
+ struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes);
+ if (!array) return NULL;
+ UPB_PRIVATE(_upb_Array_SetTaggedPtr)
+ (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2);
+ array->UPB_ONLYBITS(size) = 0;
+ array->UPB_PRIVATE(capacity) = init_capacity;
+ return array;
+}
+
+// Resizes the capacity of the array to be at least min_size.
+bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size,
+ upb_Arena* arena);
+
+UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
+ size_t size, upb_Arena* arena) {
+ if (array->UPB_PRIVATE(capacity) < size)
+ return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena);
+ return true;
+}
+
+// Resize without initializing new elements.
+UPB_INLINE bool _upb_Array_ResizeUninitialized(struct upb_Array* array,
+ size_t size, upb_Arena* arena) {
+ UPB_ASSERT(size <= array->UPB_ONLYBITS(size) ||
+ arena); // Allow NULL arena when shrinking.
+ if (!UPB_PRIVATE(_upb_Array_Reserve)(array, size, arena)) return false;
+ array->UPB_ONLYBITS(size) = size;
+ return true;
+}
+
+// This function is intended for situations where elem_size is compile-time
+// constant or a known expression of the form (1 << lg2), so that the expression
+// i*elem_size does not result in an actual multiplication.
+UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i,
+ const void* data,
+ size_t elem_size) {
+ UPB_ASSERT(i < array->UPB_ONLYBITS(size));
+ UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array));
+ char* arr_data = (char*)_upb_array_ptr(array);
+ memcpy(arr_data + (i * elem_size), data, elem_size);
+}
+
+// LINT.ThenChange(
+// GoogleInternalName1,
+//)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#undef _UPB_ARRAY_MASK_IMM
+#undef _UPB_ARRAY_MASK_LG2
+#undef _UPB_ARRAY_MASK_ALL
+
+
+#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */
+
+#ifndef UPB_MESSAGE_INTERNAL_MAP_H_
+#define UPB_MESSAGE_INTERNAL_MAP_H_
+
+#include <stddef.h>
+#include <string.h>
+
+
+#ifndef UPB_HASH_STR_TABLE_H_
+#define UPB_HASH_STR_TABLE_H_
+
+
+/*
+ * 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>
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* upb_value ******************************************************************/
+
+typedef struct {
+ uint64_t val;
+} upb_value;
+
+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) \
+ 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)
+FUNCS(int64, int64, int64_t, int64_t)
+FUNCS(uint32, uint32, uint32_t, uint32_t)
+FUNCS(uint64, uint64, uint64_t, uint64_t)
+FUNCS(bool, _bool, bool, bool)
+FUNCS(cstr, cstr, char*, uintptr_t)
+FUNCS(uintptr, uptr, uintptr_t, uintptr_t)
+FUNCS(ptr, ptr, void*, uintptr_t)
+FUNCS(constptr, constptr, const void*, uintptr_t)
+
+#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;
+}
+
+/* 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
+
+
+#endif /* UPB_HASH_COMMON_H_ */
+
+// Must be last.
+
+typedef struct {
+ upb_table t;
+} upb_strtable;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Initialize a table. If memory allocation failed, false is returned and
+// the table is uninitialized.
+bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a);
+
+// Returns the number of values in the table.
+UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) {
+ return t->t.count;
+}
+
+void upb_strtable_clear(upb_strtable* t);
+
+// Inserts the given key into the hashtable with the given value.
+// The key must not already exist in the hash table. The key is not required
+// to be NULL-terminated, and the table will make an internal copy of the key.
+//
+// If a table resize was required but memory allocation failed, false is
+// returned and the table is unchanged. */
+bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len,
+ upb_value val, upb_Arena* a);
+
+// Looks up key in this table, returning "true" if the key was found.
+// If v is non-NULL, copies the value for this key into *v.
+bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
+ upb_value* v);
+
+// For NULL-terminated strings.
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key,
+ upb_value* v) {
+ return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+// Removes an item from the table. Returns true if the remove was successful,
+// and stores the removed item in *val if non-NULL.
+bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len,
+ upb_value* val);
+
+UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key,
+ upb_value* v) {
+ return upb_strtable_remove2(t, key, strlen(key), v);
+}
+
+// Exposed for testing only.
+bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a);
+
+/* Iteration over strtable:
+ *
+ * intptr_t iter = UPB_STRTABLE_BEGIN;
+ * upb_StringView key;
+ * upb_value val;
+ * while (upb_strtable_next2(t, &key, &val, &iter)) {
+ * // ...
+ * }
+ */
+
+#define UPB_STRTABLE_BEGIN -1
+
+bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key,
+ upb_value* val, intptr_t* iter);
+void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter);
+void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v);
+
+/* DEPRECATED iterators, slated for removal.
+ *
+ * Iterators for string tables. We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ * - we must be able to guarantee that we don't crash or corrupt memory even if
+ * the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ * - iterators must be copyable
+ * - iterators must be comparable
+ * - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators. upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed. Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+/* upb_strtable_iter **********************************************************/
+
+/* upb_strtable_iter i;
+ * upb_strtable_begin(&i, t);
+ * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ * const char *key = upb_strtable_iter_key(&i);
+ * const upb_value val = upb_strtable_iter_value(&i);
+ * // ...
+ * }
+ */
+
+typedef struct {
+ const upb_strtable* t;
+ size_t index;
+} upb_strtable_iter;
+
+UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) {
+ return &i->t->t.entries[i->index];
+}
+
+void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t);
+void upb_strtable_next(upb_strtable_iter* i);
+bool upb_strtable_done(const upb_strtable_iter* i);
+upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter* i);
+void upb_strtable_iter_setdone(upb_strtable_iter* i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter* i1,
+ const upb_strtable_iter* i2);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_HASH_STR_TABLE_H_ */
+
+// Must be last.
+
+typedef enum {
+ kUpb_MapInsertStatus_Inserted = 0,
+ kUpb_MapInsertStatus_Replaced = 1,
+ kUpb_MapInsertStatus_OutOfMemory = 2,
+} upb_MapInsertStatus;
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+struct upb_Map {
+ // Size of key and val, based on the map type.
+ // Strings are represented as '0' because they must be handled specially.
+ char key_size;
+ char val_size;
+
+ upb_strtable table;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Converting between internal table representation and user values.
+//
+// _upb_map_tokey() and _upb_map_fromkey() are inverses.
+// _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
+//
+// These functions account for the fact that strings are treated differently
+// from other types when stored in a map.
+
+UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) {
+ if (size == UPB_MAPTYPE_STRING) {
+ return *(upb_StringView*)key;
+ } else {
+ return upb_StringView_FromDataAndSize((const char*)key, size);
+ }
+}
+
+UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) {
+ if (size == UPB_MAPTYPE_STRING) {
+ memcpy(out, &key, sizeof(key));
+ } else {
+ memcpy(out, key.data, size);
+ }
+}
+
+UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size,
+ upb_value* msgval, upb_Arena* a) {
+ if (size == UPB_MAPTYPE_STRING) {
+ upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp));
+ if (!strp) return false;
+ *strp = *(upb_StringView*)val;
+ *msgval = upb_value_ptr(strp);
+ } else {
+ memcpy(msgval, val, size);
+ }
+ return true;
+}
+
+UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
+ if (size == UPB_MAPTYPE_STRING) {
+ const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val);
+ memcpy(out, strp, sizeof(upb_StringView));
+ } else {
+ memcpy(out, &val, size);
+ }
+}
+
+UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) {
+ upb_strtable_iter it;
+ it.t = &map->table;
+ it.index = *iter;
+ upb_strtable_next(&it);
+ *iter = it.index;
+ if (upb_strtable_done(&it)) return NULL;
+ return (void*)str_tabent(&it);
+}
+
+UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) {
+ upb_strtable_clear(&map->table);
+}
+
+UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key,
+ size_t key_size, upb_value* val) {
+ upb_StringView k = _upb_map_tokey(key, key_size);
+ return upb_strtable_remove2(&map->table, k.data, k.size, val);
+}
+
+UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key,
+ size_t key_size, void* val, size_t val_size) {
+ upb_value tabval;
+ upb_StringView k = _upb_map_tokey(key, key_size);
+ bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
+ if (ret && val) {
+ _upb_map_fromvalue(tabval, val, val_size);
+ }
+ return ret;
+}
+
+UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map,
+ const void* key, size_t key_size,
+ void* val, size_t val_size,
+ upb_Arena* a) {
+ upb_StringView strkey = _upb_map_tokey(key, key_size);
+ upb_value tabval = {0};
+ if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
+ return kUpb_MapInsertStatus_OutOfMemory;
+ }
+
+ // TODO: add overwrite operation to minimize number of lookups.
+ bool removed =
+ upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
+ if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) {
+ return kUpb_MapInsertStatus_OutOfMemory;
+ }
+ return removed ? kUpb_MapInsertStatus_Replaced
+ : kUpb_MapInsertStatus_Inserted;
+}
+
+UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) {
+ return map->table.t.count;
+}
+
+// Strings/bytes are special-cased in maps.
+extern char _upb_Map_CTypeSizeTable[12];
+
+UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) {
+ return _upb_Map_CTypeSizeTable[ctype];
+}
+
+// Creates a new map on the given arena with this key/value type.
+struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */
/*
** Our memory representation for parsing tables and messages themselves.
@@ -1004,110 +1400,23 @@
** The definitions in this file are internal to upb.
**/
-#ifndef UPB_MESSAGE_INTERNAL_H_
-#define UPB_MESSAGE_INTERNAL_H_
+#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
+#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
#include <stdlib.h>
#include <string.h>
-#ifndef UPB_MINI_TABLE_INTERNAL_TYPES_H_
-#define UPB_MINI_TABLE_INTERNAL_TYPES_H_
-
-typedef struct upb_Message_InternalData upb_Message_InternalData;
-
-typedef struct {
- union {
- upb_Message_InternalData* internal;
-
- // Force 8-byte alignment, since the data members may contain members that
- // require 8-byte alignment.
- double d;
- };
-} upb_Message_Internal;
-
-#endif // UPB_MINI_TABLE_INTERNAL_TYPES_H_
-
-#ifndef UPB_MINI_TABLE_MESSAGE_H_
-#define UPB_MINI_TABLE_MESSAGE_H_
+#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
+#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
-#ifndef UPB_MINI_TABLE_ENUM_H_
-#define UPB_MINI_TABLE_ENUM_H_
+#ifndef UPB_MINI_TABLE_EXTENSION_H_
+#define UPB_MINI_TABLE_EXTENSION_H_
#include <stdint.h>
-#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_
-#define UPB_MINI_TABLE_INTERNAL_ENUM_H_
-
-#include <stdint.h>
-
-// Must be last.
-
-struct upb_MiniTableEnum {
- uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask.
- uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield.
- uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow.
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(
- const struct upb_MiniTableEnum* e, uint32_t val) {
- if (UPB_LIKELY(val < 64)) {
- const uint64_t mask =
- e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32);
- const uint64_t bit = 1ULL << val;
- return (mask & bit) != 0;
- }
- if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) {
- const uint32_t mask = e->UPB_PRIVATE(data)[val / 32];
- const uint32_t bit = 1ULL << (val % 32);
- return (mask & bit) != 0;
- }
-
- // OPT: binary search long lists?
- const uint32_t* start =
- &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32];
- const uint32_t* limit = &e->UPB_PRIVATE(
- data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)];
- for (const uint32_t* p = start; p < limit; p++) {
- if (*p == val) return true;
- }
- return false;
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */
-
-// Must be last
-
-typedef struct upb_MiniTableEnum upb_MiniTableEnum;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Validates enum value against range defined by enum mini table.
-UPB_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e,
- uint32_t val) {
- return UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(e, val);
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MINI_TABLE_ENUM_H_ */
-
#ifndef UPB_MINI_TABLE_FIELD_H_
#define UPB_MINI_TABLE_FIELD_H_
@@ -1457,8 +1766,8 @@
#endif /* UPB_MINI_TABLE_FIELD_H_ */
-#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_
-#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_
+#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_
+#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_
#include <stdint.h>
@@ -1510,6 +1819,134 @@
// Must be last.
+struct upb_MiniTableExtension {
+ // Do not move this field. We need to be able to alias pointers.
+ struct upb_MiniTableField UPB_PRIVATE(field);
+
+ const struct upb_MiniTable* UPB_PRIVATE(extendee);
+ union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE const struct upb_MiniTableField* UPB_PRIVATE(
+ _upb_MiniTableExtension_AsField)(const struct upb_MiniTableExtension* e) {
+ return (const struct upb_MiniTableField*)&e->UPB_PRIVATE(field);
+}
+
+UPB_INLINE uint32_t UPB_PRIVATE(_upb_MiniTableExtension_Number)(
+ const struct upb_MiniTableExtension* e) {
+ return e->UPB_PRIVATE(field).UPB_ONLYBITS(number);
+}
+
+UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(
+ _upb_MiniTableExtension_GetSubMessage)(
+ const struct upb_MiniTableExtension* e) {
+ return UPB_PRIVATE(_upb_MiniTableSub_Message)(e->UPB_PRIVATE(sub));
+}
+
+UPB_INLINE void UPB_PRIVATE(_upb_MiniTableExtension_SetSubMessage)(
+ struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) {
+ e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */
+
+#ifndef UPB_MINI_TABLE_MESSAGE_H_
+#define UPB_MINI_TABLE_MESSAGE_H_
+
+
+#ifndef UPB_MINI_TABLE_ENUM_H_
+#define UPB_MINI_TABLE_ENUM_H_
+
+#include <stdint.h>
+
+
+#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_
+#define UPB_MINI_TABLE_INTERNAL_ENUM_H_
+
+#include <stdint.h>
+
+// Must be last.
+
+struct upb_MiniTableEnum {
+ uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask.
+ uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield.
+ uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow.
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(
+ const struct upb_MiniTableEnum* e, uint32_t val) {
+ if (UPB_LIKELY(val < 64)) {
+ const uint64_t mask =
+ e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32);
+ const uint64_t bit = 1ULL << val;
+ return (mask & bit) != 0;
+ }
+ if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) {
+ const uint32_t mask = e->UPB_PRIVATE(data)[val / 32];
+ const uint32_t bit = 1ULL << (val % 32);
+ return (mask & bit) != 0;
+ }
+
+ // OPT: binary search long lists?
+ const uint32_t* start =
+ &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32];
+ const uint32_t* limit = &e->UPB_PRIVATE(
+ data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)];
+ for (const uint32_t* p = start; p < limit; p++) {
+ if (*p == val) return true;
+ }
+ return false;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */
+
+// Must be last
+
+typedef struct upb_MiniTableEnum upb_MiniTableEnum;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Validates enum value against range defined by enum mini table.
+UPB_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e,
+ uint32_t val) {
+ return UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(e, val);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_ENUM_H_ */
+
+#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_
+#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_
+
+#include <stdint.h>
+
+
+// Must be last.
+
struct upb_Decoder;
struct upb_Message;
typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
@@ -1733,140 +2170,6 @@
// Must be last.
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const float kUpb_FltInfinity;
-extern const double kUpb_Infinity;
-extern const double kUpb_NaN;
-
-/* Internal members of a upb_Message that track unknown fields and/or
- * extensions. We can change this without breaking binary compatibility. We put
- * these before the user's data. The user's upb_Message* points after the
- * upb_Message_Internal. */
-
-struct upb_Message_InternalData {
- /* Total size of this structure, including the data that follows.
- * Must be aligned to 8, which is alignof(upb_Extension) */
- uint32_t size;
-
- /* Offsets relative to the beginning of this structure.
- *
- * Unknown data grows forward from the beginning to unknown_end.
- * Extension data grows backward from size to ext_begin.
- * When the two meet, we're out of data and have to realloc.
- *
- * If we imagine that the final member of this struct is:
- * char data[size - overhead]; // overhead =
- * sizeof(upb_Message_InternalData)
- *
- * Then we have:
- * unknown data: data[0 .. (unknown_end - overhead)]
- * extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
- uint32_t unknown_end;
- uint32_t ext_begin;
- /* Data follows, as if there were an array:
- * char data[size - sizeof(upb_Message_InternalData)]; */
-};
-
-UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* m) {
- return m->UPB_PRIVATE(size) + sizeof(upb_Message_Internal);
-}
-
-// Inline version upb_Message_New(), for internal use.
-UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
- upb_Arena* arena) {
- size_t size = upb_msg_sizeof(mini_table);
- void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
- if (UPB_UNLIKELY(!mem)) return NULL;
- struct upb_Message* msg =
- UPB_PTR_AT(mem, sizeof(upb_Message_Internal), struct upb_Message);
- memset(mem, 0, size);
- return msg;
-}
-
-UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
- const struct upb_Message* msg) {
- ptrdiff_t size = sizeof(upb_Message_Internal);
- return (upb_Message_Internal*)((char*)msg - size);
-}
-
-// Discards the unknown fields for this message only.
-void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg);
-
-// Adds unknown data (serialized protobuf data) to the given message.
-// The data is copied into the message instance.
-bool UPB_PRIVATE(_upb_Message_AddUnknown)(struct upb_Message* msg,
- const char* data, size_t len,
- upb_Arena* arena);
-
-bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
- upb_Arena* arena);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MESSAGE_INTERNAL_H_ */
-
-#ifndef UPB_MINI_TABLE_EXTENSION_H_
-#define UPB_MINI_TABLE_EXTENSION_H_
-
-#include <stdint.h>
-
-
-#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_
-#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_
-
-#include <stdint.h>
-
-
-// Must be last.
-
-struct upb_MiniTableExtension {
- // Do not move this field. We need to be able to alias pointers.
- struct upb_MiniTableField UPB_PRIVATE(field);
-
- const struct upb_MiniTable* UPB_PRIVATE(extendee);
- union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-UPB_INLINE const struct upb_MiniTableField* UPB_PRIVATE(
- _upb_MiniTableExtension_AsField)(const struct upb_MiniTableExtension* e) {
- return (const struct upb_MiniTableField*)&e->UPB_PRIVATE(field);
-}
-
-UPB_INLINE uint32_t UPB_PRIVATE(_upb_MiniTableExtension_Number)(
- const struct upb_MiniTableExtension* e) {
- return e->UPB_PRIVATE(field).UPB_ONLYBITS(number);
-}
-
-UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(
- _upb_MiniTableExtension_GetSubMessage)(
- const struct upb_MiniTableExtension* e) {
- return UPB_PRIVATE(_upb_MiniTableSub_Message)(e->UPB_PRIVATE(sub));
-}
-
-UPB_INLINE void UPB_PRIVATE(_upb_MiniTableExtension_SetSubMessage)(
- struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) {
- e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m;
-}
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */
-
-// Must be last.
-
typedef struct upb_MiniTableExtension upb_MiniTableExtension;
#ifdef __cplusplus
@@ -1947,557 +2250,243 @@
#endif /* UPB_MESSAGE_INTERNAL_EXTENSION_H_ */
-// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
-
-#ifndef UPB_MESSAGE_INTERNAL_MAP_H_
-#define UPB_MESSAGE_INTERNAL_MAP_H_
-
-#include <stddef.h>
-#include <string.h>
-
-
-#ifndef UPB_HASH_STR_TABLE_H_
-#define UPB_HASH_STR_TABLE_H_
-
-
-/*
- * 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>
-
-
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
-/* upb_value ******************************************************************/
+extern const float kUpb_FltInfinity;
+extern const double kUpb_Infinity;
+extern const double kUpb_NaN;
+
+/* Internal members of a upb_Message that track unknown fields and/or
+ * extensions. We can change this without breaking binary compatibility. We put
+ * these before the user's data. The user's upb_Message* points after the
+ * upb_Message_Internal. */
typedef struct {
- uint64_t val;
-} upb_value;
+ /* Total size of this structure, including the data that follows.
+ * Must be aligned to 8, which is alignof(upb_Extension) */
+ uint32_t size;
-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) \
- 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)
-FUNCS(int64, int64, int64_t, int64_t)
-FUNCS(uint32, uint32, uint32_t, uint32_t)
-FUNCS(uint64, uint64, uint64_t, uint64_t)
-FUNCS(bool, _bool, bool, bool)
-FUNCS(cstr, cstr, char*, uintptr_t)
-FUNCS(uintptr, uptr, uintptr_t, uintptr_t)
-FUNCS(ptr, ptr, void*, uintptr_t)
-FUNCS(constptr, constptr, const void*, uintptr_t)
-
-#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;
-}
-
-/* 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;
+ /* Offsets relative to the beginning of this structure.
+ *
+ * Unknown data grows forward from the beginning to unknown_end.
+ * Extension data grows backward from size to ext_begin.
+ * When the two meet, we're out of data and have to realloc.
+ *
+ * If we imagine that the final member of this struct is:
+ * char data[size - overhead]; // overhead =
+ * sizeof(upb_Message_InternalData)
+ *
+ * Then we have:
+ * unknown data: data[0 .. (unknown_end - overhead)]
+ * extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
+ uint32_t unknown_end;
+ uint32_t ext_begin;
+ /* Data follows, as if there were an array:
+ * char data[size - sizeof(upb_Message_InternalData)]; */
+} upb_Message_InternalData;
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;
+ union {
+ upb_Message_InternalData* internal;
-UPB_INLINE size_t upb_table_size(const upb_table* t) {
- return t->size_lg2 ? 1 << t->size_lg2 : 0;
-}
+ // Force 8-byte alignment, since the data members may contain members that
+ // require 8-byte alignment.
+ double d;
+ };
+} upb_Message_Internal;
-// 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
-
-
-#endif /* UPB_HASH_COMMON_H_ */
-
-// Must be last.
-
-typedef struct {
- upb_table t;
-} upb_strtable;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Initialize a table. If memory allocation failed, false is returned and
-// the table is uninitialized.
-bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a);
-
-// Returns the number of values in the table.
-UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) {
- return t->t.count;
-}
-
-void upb_strtable_clear(upb_strtable* t);
-
-// Inserts the given key into the hashtable with the given value.
-// The key must not already exist in the hash table. The key is not required
-// to be NULL-terminated, and the table will make an internal copy of the key.
-//
-// If a table resize was required but memory allocation failed, false is
-// returned and the table is unchanged. */
-bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len,
- upb_value val, upb_Arena* a);
-
-// Looks up key in this table, returning "true" if the key was found.
-// If v is non-NULL, copies the value for this key into *v.
-bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
- upb_value* v);
-
-// For NULL-terminated strings.
-UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key,
- upb_value* v) {
- return upb_strtable_lookup2(t, key, strlen(key), v);
-}
-
-// Removes an item from the table. Returns true if the remove was successful,
-// and stores the removed item in *val if non-NULL.
-bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len,
- upb_value* val);
-
-UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key,
- upb_value* v) {
- return upb_strtable_remove2(t, key, strlen(key), v);
-}
-
-// Exposed for testing only.
-bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a);
-
-/* Iteration over strtable:
- *
- * intptr_t iter = UPB_STRTABLE_BEGIN;
- * upb_StringView key;
- * upb_value val;
- * while (upb_strtable_next2(t, &key, &val, &iter)) {
- * // ...
- * }
- */
-
-#define UPB_STRTABLE_BEGIN -1
-
-bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key,
- upb_value* val, intptr_t* iter);
-void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter);
-void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v);
-
-/* DEPRECATED iterators, slated for removal.
- *
- * Iterators for string tables. We are subject to some kind of unusual
- * design constraints:
- *
- * For high-level languages:
- * - we must be able to guarantee that we don't crash or corrupt memory even if
- * the program accesses an invalidated iterator.
- *
- * For C++11 range-based for:
- * - iterators must be copyable
- * - iterators must be comparable
- * - it must be possible to construct an "end" value.
- *
- * Iteration order is undefined.
- *
- * Modifying the table invalidates iterators. upb_{str,int}table_done() is
- * guaranteed to work even on an invalidated iterator, as long as the table it
- * is iterating over has not been freed. Calling next() or accessing data from
- * an invalidated iterator yields unspecified elements from the table, but it is
- * guaranteed not to crash and to return real table elements (except when done()
- * is true). */
-/* upb_strtable_iter **********************************************************/
-
-/* upb_strtable_iter i;
- * upb_strtable_begin(&i, t);
- * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- * const char *key = upb_strtable_iter_key(&i);
- * const upb_value val = upb_strtable_iter_value(&i);
- * // ...
- * }
- */
-
-typedef struct {
- const upb_strtable* t;
- size_t index;
-} upb_strtable_iter;
-
-UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) {
- return &i->t->t.entries[i->index];
-}
-
-void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t);
-void upb_strtable_next(upb_strtable_iter* i);
-bool upb_strtable_done(const upb_strtable_iter* i);
-upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i);
-upb_value upb_strtable_iter_value(const upb_strtable_iter* i);
-void upb_strtable_iter_setdone(upb_strtable_iter* i);
-bool upb_strtable_iter_isequal(const upb_strtable_iter* i1,
- const upb_strtable_iter* i2);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_HASH_STR_TABLE_H_ */
-
-#ifndef UPB_MESSAGE_MAP_H_
-#define UPB_MESSAGE_MAP_H_
-
-#include <stddef.h>
-
-
-// Must be last.
-
-typedef struct upb_Map upb_Map;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Creates a new map on the given arena with the given key/value size.
-UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type,
- upb_CType value_type);
-
-// Returns the number of entries in the map.
-UPB_API size_t upb_Map_Size(const upb_Map* map);
-
-// Stores a value for the given key into |*val| (or the zero value if the key is
-// not present). Returns whether the key was present. The |val| pointer may be
-// NULL, in which case the function tests whether the given key is present.
-UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
- upb_MessageValue* val);
-
-// Removes all entries in the map.
-UPB_API void upb_Map_Clear(upb_Map* map);
-
-typedef enum {
- kUpb_MapInsertStatus_Inserted = 0,
- kUpb_MapInsertStatus_Replaced = 1,
- kUpb_MapInsertStatus_OutOfMemory = 2,
-} upb_MapInsertStatus;
-
-// Sets the given key to the given value, returning whether the key was inserted
-// or replaced. If the key was inserted, then any existing iterators will be
-// invalidated.
-UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
- upb_MessageValue val,
- upb_Arena* arena);
-
-// Sets the given key to the given value. Returns false if memory allocation
-// failed. If the key is newly inserted, then any existing iterators will be
-// invalidated.
-UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key,
- upb_MessageValue val, upb_Arena* arena) {
- return upb_Map_Insert(map, key, val, arena) !=
- kUpb_MapInsertStatus_OutOfMemory;
-}
-
-// Deletes this key from the table. Returns true if the key was present.
-// If present and |val| is non-NULL, stores the deleted value.
-UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key,
- upb_MessageValue* val);
-
-// (DEPRECATED and going away soon. Do not use.)
-UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key,
- upb_MessageValue* val) {
- return upb_Map_Delete(map, key, val);
-}
-
-// Map iteration:
-//
-// size_t iter = kUpb_Map_Begin;
-// upb_MessageValue key, val;
-// while (upb_Map_Next(map, &key, &val, &iter)) {
-// ...
-// }
-
-#define kUpb_Map_Begin ((size_t)-1)
-
-// Advances to the next entry. Returns false if no more entries are present.
-// Otherwise returns true and populates both *key and *value.
-UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
- upb_MessageValue* val, size_t* iter);
-
-// Sets the value for the entry pointed to by iter.
-// WARNING: this does not currently work for string values!
-UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter,
- upb_MessageValue val);
-
-// DEPRECATED iterator, slated for removal.
-
-/* Map iteration:
- *
- * size_t iter = kUpb_Map_Begin;
- * while (upb_MapIterator_Next(map, &iter)) {
- * upb_MessageValue key = upb_MapIterator_Key(map, iter);
- * upb_MessageValue val = upb_MapIterator_Value(map, iter);
- * }
- */
-
-// Advances to the next entry. Returns false if no more entries are present.
-UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
-
-// Returns true if the iterator still points to a valid entry, or false if the
-// iterator is past the last element. It is an error to call this function with
-// kUpb_Map_Begin (you must call next() at least once first).
-UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
-
-// Returns the key and value for this entry of the map.
-UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
-UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MESSAGE_MAP_H_ */
-
-// Must be last.
-
-struct upb_Map {
- // Size of key and val, based on the map type.
- // Strings are represented as '0' because they must be handled specially.
- char key_size;
- char val_size;
-
- upb_strtable table;
+struct upb_Message {
+ int unused; // Placeholder cuz Windows won't compile an empty struct.
};
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Converting between internal table representation and user values.
-//
-// _upb_map_tokey() and _upb_map_fromkey() are inverses.
-// _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
-//
-// These functions account for the fact that strings are treated differently
-// from other types when stored in a map.
-
-UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- return *(upb_StringView*)key;
- } else {
- return upb_StringView_FromDataAndSize((const char*)key, size);
- }
+UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* m) {
+ return m->UPB_PRIVATE(size) + sizeof(upb_Message_Internal);
}
-UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- memcpy(out, &key, sizeof(key));
- } else {
- memcpy(out, key.data, size);
- }
+// Inline version upb_Message_New(), for internal use.
+UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
+ upb_Arena* arena) {
+ size_t size = upb_msg_sizeof(mini_table);
+ void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
+ if (UPB_UNLIKELY(!mem)) return NULL;
+ struct upb_Message* msg =
+ UPB_PTR_AT(mem, sizeof(upb_Message_Internal), struct upb_Message);
+ memset(mem, 0, size);
+ return msg;
}
-UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size,
- upb_value* msgval, upb_Arena* a) {
- if (size == UPB_MAPTYPE_STRING) {
- upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp));
- if (!strp) return false;
- *strp = *(upb_StringView*)val;
- *msgval = upb_value_ptr(strp);
- } else {
- memcpy(msgval, val, size);
- }
- return true;
+UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
+ const struct upb_Message* msg) {
+ ptrdiff_t size = sizeof(upb_Message_Internal);
+ return (upb_Message_Internal*)((char*)msg - size);
}
-UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
- if (size == UPB_MAPTYPE_STRING) {
- const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val);
- memcpy(out, strp, sizeof(upb_StringView));
- } else {
- memcpy(out, &val, size);
- }
-}
+// Discards the unknown fields for this message only.
+void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg);
-UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) {
- upb_strtable_iter it;
- it.t = &map->table;
- it.index = *iter;
- upb_strtable_next(&it);
- *iter = it.index;
- if (upb_strtable_done(&it)) return NULL;
- return (void*)str_tabent(&it);
-}
+// Adds unknown data (serialized protobuf data) to the given message.
+// The data is copied into the message instance.
+bool UPB_PRIVATE(_upb_Message_AddUnknown)(struct upb_Message* msg,
+ const char* data, size_t len,
+ upb_Arena* arena);
-UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) {
- upb_strtable_clear(&map->table);
-}
-
-UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key,
- size_t key_size, upb_value* val) {
- upb_StringView k = _upb_map_tokey(key, key_size);
- return upb_strtable_remove2(&map->table, k.data, k.size, val);
-}
-
-UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key,
- size_t key_size, void* val, size_t val_size) {
- upb_value tabval;
- upb_StringView k = _upb_map_tokey(key, key_size);
- bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
- if (ret && val) {
- _upb_map_fromvalue(tabval, val, val_size);
- }
- return ret;
-}
-
-UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map,
- const void* key, size_t key_size,
- void* val, size_t val_size,
- upb_Arena* a) {
- upb_StringView strkey = _upb_map_tokey(key, key_size);
- upb_value tabval = {0};
- if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
- return kUpb_MapInsertStatus_OutOfMemory;
- }
-
- // TODO: add overwrite operation to minimize number of lookups.
- bool removed =
- upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
- if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) {
- return kUpb_MapInsertStatus_OutOfMemory;
- }
- return removed ? kUpb_MapInsertStatus_Replaced
- : kUpb_MapInsertStatus_Inserted;
-}
-
-UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) {
- return map->table.t.count;
-}
-
-// Strings/bytes are special-cased in maps.
-extern char _upb_Map_CTypeSizeTable[12];
-
-UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) {
- return _upb_Map_CTypeSizeTable[ctype];
-}
-
-// Creates a new map on the given arena with this key/value type.
-struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size);
+bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
+ upb_Arena* arena);
#ifdef __cplusplus
} /* extern "C" */
#endif
-#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */
+#endif /* UPB_MESSAGE_INTERNAL_MESSAGE_H_ */
+
+#ifndef UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_
+#define UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_
+
+#include <stdint.h>
+
+
+// Must be last.
+
+typedef uintptr_t upb_TaggedMessagePtr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Internal-only because empty messages cannot be created by the user.
+UPB_INLINE upb_TaggedMessagePtr
+UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(struct upb_Message* ptr, bool empty) {
+ UPB_ASSERT(((uintptr_t)ptr & 1) == 0);
+ return (uintptr_t)ptr | (empty ? 1 : 0);
+}
+
+UPB_INLINE bool UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(
+ upb_TaggedMessagePtr ptr) {
+ return ptr & 1;
+}
+
+UPB_INLINE struct upb_Message* UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(
+ upb_TaggedMessagePtr ptr) {
+ return (struct upb_Message*)(ptr & ~(uintptr_t)1);
+}
+
+UPB_INLINE struct upb_Message* UPB_PRIVATE(
+ _upb_TaggedMessagePtr_GetNonEmptyMessage)(upb_TaggedMessagePtr ptr) {
+ UPB_ASSERT(!UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(ptr));
+ return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr);
+}
+
+UPB_INLINE struct upb_Message* UPB_PRIVATE(
+ _upb_TaggedMessagePtr_GetEmptyMessage)(upb_TaggedMessagePtr ptr) {
+ UPB_ASSERT(UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(ptr));
+ return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ */
+
+typedef union {
+ bool bool_val;
+ float float_val;
+ double double_val;
+ int32_t int32_val;
+ int64_t int64_val;
+ uint32_t uint32_val;
+ uint64_t uint64_val;
+ const struct upb_Array* array_val;
+ const struct upb_Map* map_val;
+ const struct upb_Message* msg_val;
+ upb_StringView str_val;
+
+ // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of
+ // msg_val if unlinked sub-messages may possibly be in use. See the
+ // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more
+ // information.
+ upb_TaggedMessagePtr tagged_msg_val;
+} upb_MessageValue;
+
+typedef union {
+ struct upb_Array* array;
+ struct upb_Map* map;
+ struct upb_Message* msg;
+} upb_MutableMessageValue;
+
+#endif /* UPB_MESSAGE_VALUE_H_ */
+
+// Must be last.
+
+typedef struct upb_Array upb_Array;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Creates a new array on the given arena that holds elements of this type.
+UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
+
+// Returns the number of elements in the array.
+UPB_API size_t upb_Array_Size(const upb_Array* arr);
+
+// Returns the given element, which must be within the array's current size.
+UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i);
+
+// Sets the given element, which must be within the array's current size.
+UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val);
+
+// Appends an element to the array. Returns false on allocation failure.
+UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val,
+ upb_Arena* arena);
+
+// Moves elements within the array using memmove().
+// Like memmove(), the source and destination elements may be overlapping.
+UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
+ size_t count);
+
+// Inserts one or more empty elements into the array.
+// Existing elements are shifted right.
+// The new elements have undefined state and must be set with `upb_Array_Set()`.
+// REQUIRES: `i <= upb_Array_Size(arr)`
+UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
+ upb_Arena* arena);
+
+// Deletes one or more elements from the array.
+// Existing elements are shifted left.
+// REQUIRES: `i + count <= upb_Array_Size(arr)`
+UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
+
+// Changes the size of a vector. New elements are initialized to NULL/0.
+// Returns false on allocation failure.
+UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena);
+
+// Returns pointer to array data.
+UPB_API const void* upb_Array_DataPtr(const upb_Array* arr);
+
+// Returns mutable pointer to array data.
+UPB_API void* upb_Array_MutableDataPtr(upb_Array* arr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_ARRAY_H_ */
+
+#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_
+#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
// Must be last.
@@ -2528,7 +2517,7 @@
// Hasbit access ///////////////////////////////////////////////////////////////
UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)(
- const upb_Message* msg, const upb_MiniTableField* f) {
+ const struct upb_Message* msg, const upb_MiniTableField* f) {
const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
@@ -2536,7 +2525,7 @@
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)(
- const upb_Message* msg, const upb_MiniTableField* f) {
+ const struct upb_Message* msg, const upb_MiniTableField* f) {
const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
@@ -2544,7 +2533,7 @@
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)(
- const upb_Message* msg, const upb_MiniTableField* f) {
+ const struct upb_Message* msg, const upb_MiniTableField* f) {
const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f);
const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f);
@@ -2554,18 +2543,18 @@
// Oneof case access ///////////////////////////////////////////////////////////
UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)(
- upb_Message* msg, const upb_MiniTableField* f) {
+ struct upb_Message* msg, const upb_MiniTableField* f) {
return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f),
uint32_t);
}
UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)(
- const upb_Message* msg, const upb_MiniTableField* f) {
- return *UPB_PRIVATE(_upb_Message_OneofCasePtr)((upb_Message*)msg, f);
+ const struct upb_Message* msg, const upb_MiniTableField* f) {
+ return *UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f);
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)(
- upb_Message* msg, const upb_MiniTableField* f) {
+ struct upb_Message* msg, const upb_MiniTableField* f) {
*UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f) =
upb_MiniTableField_Number(f);
}
@@ -2574,18 +2563,18 @@
// LINT.ThenChange(GoogleInternalName2)
-UPB_INLINE void* _upb_MiniTableField_GetPtr(upb_Message* msg,
+UPB_INLINE void* _upb_MiniTableField_GetPtr(struct upb_Message* msg,
const upb_MiniTableField* field) {
return (char*)msg + field->UPB_ONLYBITS(offset);
}
UPB_INLINE const void* _upb_MiniTableField_GetConstPtr(
- const upb_Message* msg, const upb_MiniTableField* field) {
+ const struct upb_Message* msg, const upb_MiniTableField* field) {
return (char*)msg + field->UPB_ONLYBITS(offset);
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)(
- upb_Message* msg, const upb_MiniTableField* field) {
+ struct upb_Message* msg, const upb_MiniTableField* field) {
if (field->presence > 0) {
UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field);
} else if (upb_MiniTableField_IsInOneof(field)) {
@@ -2671,13 +2660,13 @@
// returned bool value may be ignored since it will always succeed.
UPB_INLINE bool _upb_Message_HasExtensionField(
- const upb_Message* msg, const upb_MiniTableExtension* ext) {
+ const struct upb_Message* msg, const upb_MiniTableExtension* ext) {
UPB_ASSERT(upb_MiniTableField_HasPresence(&ext->UPB_PRIVATE(field)));
return _upb_Message_Getext(msg, ext) != NULL;
}
UPB_INLINE bool _upb_Message_HasNonExtensionField(
- const upb_Message* msg, const upb_MiniTableField* field) {
+ const struct upb_Message* msg, const upb_MiniTableField* field) {
UPB_ASSERT(upb_MiniTableField_HasPresence(field));
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
if (upb_MiniTableField_IsInOneof(field)) {
@@ -2689,7 +2678,7 @@
}
static UPB_FORCEINLINE void _upb_Message_GetNonExtensionField(
- const upb_Message* msg, const upb_MiniTableField* field,
+ const struct upb_Message* msg, const upb_MiniTableField* field,
const void* default_val, void* val) {
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
if ((upb_MiniTableField_IsInOneof(field) ||
@@ -2703,7 +2692,7 @@
}
UPB_INLINE void _upb_Message_GetExtensionField(
- const upb_Message* msg, const upb_MiniTableExtension* mt_ext,
+ const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
const void* default_val, void* val) {
const struct upb_Extension* ext = _upb_Message_Getext(msg, mt_ext);
const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field);
@@ -2716,35 +2705,8 @@
}
}
-// Gets a mutable Array, Map or Message field.
-// NOTE: For repeated/map fields, the resulting upb_Array*/upb_Map* can
-// be NULL if a upb_Array/upb_Map has not been allocated yet. Array/map
-// fields do not have presence, so this is semantically identical to a
-// pointer to an empty array/map, and must be treated the same for all
-// semantic purposes.
-//
-// For message fields, the pointer is guaranteed to be NULL iff the field
-// is unset (as message fields do have presence).
-UPB_INLINE upb_MutableMessageValue _upb_Message_GetMutableField(
- const upb_Message* msg, const upb_MiniTableField* field) {
- UPB_ASSUME(!upb_MiniTableField_IsScalar(field) ||
- upb_MiniTableField_IsSubMessage(field));
-
- upb_MutableMessageValue default_val;
- default_val.msg = NULL;
-
- upb_MutableMessageValue ret;
- if (upb_MiniTableField_IsExtension(field)) {
- _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field,
- &default_val, &ret);
- } else {
- _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret);
- }
- return ret;
-}
-
UPB_INLINE void _upb_Message_SetNonExtensionField(
- upb_Message* msg, const upb_MiniTableField* field, const void* val) {
+ struct upb_Message* msg, const upb_MiniTableField* field, const void* val) {
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
UPB_PRIVATE(_upb_Message_SetPresence)(msg, field);
UPB_PRIVATE(_upb_MiniTableField_DataCopy)
@@ -2752,8 +2714,8 @@
}
UPB_INLINE bool _upb_Message_SetExtensionField(
- upb_Message* msg, const upb_MiniTableExtension* mt_ext, const void* val,
- upb_Arena* a) {
+ struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
+ const void* val, upb_Arena* a) {
UPB_ASSERT(a);
struct upb_Extension* ext = _upb_Message_GetOrCreateExtension(msg, mt_ext, a);
if (!ext) return false;
@@ -2763,7 +2725,7 @@
}
UPB_INLINE void _upb_Message_ClearExtensionField(
- upb_Message* msg, const upb_MiniTableExtension* ext_l) {
+ struct upb_Message* msg, const upb_MiniTableExtension* ext_l) {
upb_Message_Internal* in = upb_Message_Getinternal(msg);
if (!in->internal) return;
const struct upb_Extension* base =
@@ -2777,7 +2739,7 @@
}
UPB_INLINE void _upb_Message_ClearNonExtensionField(
- upb_Message* msg, const upb_MiniTableField* field) {
+ struct upb_Message* msg, const upb_MiniTableField* field) {
if (field->presence > 0) {
UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, field);
} else if (upb_MiniTableField_IsInOneof(field)) {
@@ -2791,19 +2753,19 @@
}
UPB_INLINE void _upb_Message_AssertMapIsUntagged(
- const upb_Message* msg, const upb_MiniTableField* field) {
+ const struct upb_Message* msg, const upb_MiniTableField* field) {
UPB_UNUSED(msg);
UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field);
#ifndef NDEBUG
upb_TaggedMessagePtr default_val = 0;
upb_TaggedMessagePtr tagged;
_upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged);
- UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(tagged));
+ UPB_ASSERT(!UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(tagged));
#endif
}
UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap(
- upb_Message* msg, const upb_MiniTableField* field, size_t key_size,
+ struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size,
size_t val_size, upb_Arena* arena) {
UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field);
_upb_Message_AssertMapIsUntagged(msg, field);
@@ -2830,126 +2792,192 @@
#endif // UPB_MESSAGE_INTERNAL_ACCESSORS_H_
-#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_
-#define UPB_MESSAGE_INTERNAL_ARRAY_H_
+#ifndef UPB_MESSAGE_MAP_H_
+#define UPB_MESSAGE_MAP_H_
-#include <string.h>
+#include <stddef.h>
// Must be last.
-#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit.
-#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size.
-#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2)
+typedef struct upb_Map upb_Map;
#ifdef __cplusplus
extern "C" {
#endif
-// LINT.IfChange(struct_definition)
-// Our internal representation for repeated fields.
-struct upb_Array {
- // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows:
- // 0 maps to elem size 1
- // 1 maps to elem size 4
- // 2 maps to elem size 8
- // 3 maps to elem size 16
- //
- // Bit #2 contains the frozen/immutable flag (currently unimplemented).
- uintptr_t data;
+// Creates a new map on the given arena with the given key/value size.
+UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type,
+ upb_CType value_type);
- size_t UPB_ONLYBITS(size); // The number of elements in the array.
- size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements.
-};
+// Returns the number of entries in the map.
+UPB_API size_t upb_Map_Size(const upb_Map* map);
-UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array,
- void* data, size_t lg2) {
- UPB_ASSERT(lg2 != 1);
- UPB_ASSERT(lg2 <= 4);
- const size_t bits = lg2 - (lg2 != 0);
- array->data = (uintptr_t)data | bits;
+// Stores a value for the given key into |*val| (or the zero value if the key is
+// not present). Returns whether the key was present. The |val| pointer may be
+// NULL, in which case the function tests whether the given key is present.
+UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
+ upb_MessageValue* val);
+
+// Removes all entries in the map.
+UPB_API void upb_Map_Clear(upb_Map* map);
+
+// Sets the given key to the given value, returning whether the key was inserted
+// or replaced. If the key was inserted, then any existing iterators will be
+// invalidated.
+UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue val,
+ upb_Arena* arena);
+
+// Sets the given key to the given value. Returns false if memory allocation
+// failed. If the key is newly inserted, then any existing iterators will be
+// invalidated.
+UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue val, upb_Arena* arena) {
+ return upb_Map_Insert(map, key, val, arena) !=
+ kUpb_MapInsertStatus_OutOfMemory;
}
-UPB_INLINE size_t
-UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) {
- const size_t bits = array->data & _UPB_ARRAY_MASK_LG2;
- const size_t lg2 = bits + (bits != 0);
- return lg2;
+// Deletes this key from the table. Returns true if the key was present.
+// If present and |val| is non-NULL, stores the deleted value.
+UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue* val);
+
+// (DEPRECATED and going away soon. Do not use.)
+UPB_INLINE bool upb_Map_Delete2(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue* val) {
+ return upb_Map_Delete(map, key, val);
}
-UPB_INLINE const void* _upb_array_constptr(const struct upb_Array* array) {
- UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions.
- return (void*)(array->data & ~(uintptr_t)_UPB_ARRAY_MASK_ALL);
-}
+// Map iteration:
+//
+// size_t iter = kUpb_Map_Begin;
+// upb_MessageValue key, val;
+// while (upb_Map_Next(map, &key, &val, &iter)) {
+// ...
+// }
-UPB_INLINE void* _upb_array_ptr(struct upb_Array* array) {
- return (void*)_upb_array_constptr(array);
-}
+#define kUpb_Map_Begin ((size_t)-1)
-UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena,
- size_t init_capacity,
- int elem_size_lg2) {
- UPB_ASSERT(elem_size_lg2 != 1);
- UPB_ASSERT(elem_size_lg2 <= 4);
- const size_t array_size =
- UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN);
- const size_t bytes = array_size + (init_capacity << elem_size_lg2);
- struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes);
- if (!array) return NULL;
- UPB_PRIVATE(_upb_Array_SetTaggedPtr)
- (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2);
- array->UPB_ONLYBITS(size) = 0;
- array->UPB_PRIVATE(capacity) = init_capacity;
- return array;
-}
+// Advances to the next entry. Returns false if no more entries are present.
+// Otherwise returns true and populates both *key and *value.
+UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
+ upb_MessageValue* val, size_t* iter);
-// Resizes the capacity of the array to be at least min_size.
-bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size,
- upb_Arena* arena);
+// Sets the value for the entry pointed to by iter.
+// WARNING: this does not currently work for string values!
+UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter,
+ upb_MessageValue val);
-UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
- size_t size, upb_Arena* arena) {
- if (array->UPB_PRIVATE(capacity) < size)
- return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena);
- return true;
-}
+// DEPRECATED iterator, slated for removal.
-// Resize without initializing new elements.
-UPB_INLINE bool _upb_Array_ResizeUninitialized(struct upb_Array* array,
- size_t size, upb_Arena* arena) {
- UPB_ASSERT(size <= array->UPB_ONLYBITS(size) ||
- arena); // Allow NULL arena when shrinking.
- if (!UPB_PRIVATE(_upb_Array_Reserve)(array, size, arena)) return false;
- array->UPB_ONLYBITS(size) = size;
- return true;
-}
+/* Map iteration:
+ *
+ * size_t iter = kUpb_Map_Begin;
+ * while (upb_MapIterator_Next(map, &iter)) {
+ * upb_MessageValue key = upb_MapIterator_Key(map, iter);
+ * upb_MessageValue val = upb_MapIterator_Value(map, iter);
+ * }
+ */
-// This function is intended for situations where elem_size is compile-time
-// constant or a known expression of the form (1 << lg2), so that the expression
-// i*elem_size does not result in an actual multiplication.
-UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i,
- const void* data,
- size_t elem_size) {
- UPB_ASSERT(i < array->UPB_ONLYBITS(size));
- UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array));
- char* arr_data = (char*)_upb_array_ptr(array);
- memcpy(arr_data + (i * elem_size), data, elem_size);
-}
+// Advances to the next entry. Returns false if no more entries are present.
+UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
-// LINT.ThenChange(
-// GoogleInternalName1,
-//)
+// Returns true if the iterator still points to a valid entry, or false if the
+// iterator is past the last element. It is an error to call this function with
+// kUpb_Map_Begin (you must call next() at least once first).
+UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
+
+// Returns the key and value for this entry of the map.
+UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
+UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
#ifdef __cplusplus
} /* extern "C" */
#endif
-#undef _UPB_ARRAY_MASK_IMM
-#undef _UPB_ARRAY_MASK_LG2
-#undef _UPB_ARRAY_MASK_ALL
+
+#endif /* UPB_MESSAGE_MAP_H_ */
+
+#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_
+#define UPB_MINI_TABLE_TAGGED_PTR_H_
+
+#include <stdint.h>
-#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */
+// Public APIs for message operations that do not depend on the schema.
+//
+// MiniTable-based accessors live in accessors.h.
+
+#ifndef UPB_MESSAGE_MESSAGE_H_
+#define UPB_MESSAGE_MESSAGE_H_
+
+#include <stddef.h>
+
+
+// Must be last.
+
+typedef struct upb_Extension upb_Extension;
+typedef struct upb_Message upb_Message;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Creates a new message with the given mini_table on the given arena.
+UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena);
+
+// Returns a reference to the message's unknown data.
+const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
+
+// Removes partial unknown data from message.
+void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len);
+
+// Returns the number of extensions present in this message.
+size_t upb_Message_ExtensionCount(const upb_Message* msg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_MESSAGE_H_ */
+
+// Must be last.
+
+// When a upb_Message* is stored in a message, array, or map, it is stored in a
+// tagged form. If the tag bit is set, the referenced upb_Message is of type
+// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of
+// that field's true message type. This forms the basis of what we call
+// "dynamic tree shaking."
+//
+// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for
+// more information.
+
+typedef uintptr_t upb_TaggedMessagePtr;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Users who enable unlinked sub-messages must use this to test whether a
+// message is empty before accessing it. If a message is empty, it must be
+// first promoted using the interfaces in message/promote.h.
+UPB_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr) {
+ return UPB_PRIVATE(_upb_TaggedMessagePtr_IsEmpty)(ptr);
+}
+
+UPB_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage(
+ upb_TaggedMessagePtr ptr) {
+ return UPB_PRIVATE(_upb_TaggedMessagePtr_GetNonEmptyMessage)(ptr);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */
#ifndef UPB_MINI_TABLE_SUB_H_
#define UPB_MINI_TABLE_SUB_H_
@@ -3318,7 +3346,8 @@
const upb_MiniTableField* field,
upb_Message* sub_message) {
_upb_Message_SetTaggedMessagePtr(
- msg, mini_table, field, _upb_TaggedMessagePtr_Pack(sub_message, false));
+ msg, mini_table, field,
+ UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(sub_message, false));
}
UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage(
@@ -3471,43 +3500,6 @@
#endif /* UPB_MESSAGE_MAP_GENCODE_UTIL_H_ */
-// Public APIs for message operations that do not depend on the schema.
-//
-// MiniTable-based accessors live in accessors.h.
-
-#ifndef UPB_MESSAGE_MESSAGE_H_
-#define UPB_MESSAGE_MESSAGE_H_
-
-#include <stddef.h>
-
-
-// Must be last.
-
-typedef struct upb_Extension upb_Extension;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Creates a new message with the given mini_table on the given arena.
-UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena);
-
-// Returns a reference to the message's unknown data.
-const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
-
-// Removes partial unknown data from message.
-void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len);
-
-// Returns the number of extensions present in this message.
-size_t upb_Message_ExtensionCount(const upb_Message* msg);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif /* UPB_MESSAGE_MESSAGE_H_ */
-
#ifndef UPB_MINI_TABLE_DECODE_H_
#define UPB_MINI_TABLE_DECODE_H_
@@ -12411,7 +12403,8 @@
if (s->entries) upb_gfree(s->entries);
}
-UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s,
+ const struct upb_Map* map,
_upb_sortedmap* sorted, upb_MapEntry* ent) {
if (sorted->pos == sorted->end) return false;
const upb_tabent* tabent = (const upb_tabent*)s->entries[sorted->pos++];
@@ -12436,7 +12429,7 @@
}
bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
- const upb_Map* map, _upb_sortedmap* sorted);
+ const struct upb_Map* map, _upb_sortedmap* sorted);
bool _upb_mapsorter_pushexts(_upb_mapsorter* s,
const struct upb_Extension* exts, size_t count,