Auto-generate files after cl/601848001

pull/15608/head
Protobuf Team Bot 10 months ago
parent 29b4ed7289
commit 886a0b15cd
  1. 128
      php/ext/google/protobuf/php-upb.c
  2. 541
      php/ext/google/protobuf/php-upb.h
  3. 128
      ruby/ext/google/protobuf_c/ruby-upb.c
  4. 541
      ruby/ext/google/protobuf_c/ruby-upb.h

@ -3617,6 +3617,7 @@ static bool upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg,
bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
const upb_MessageDef* m, const upb_DefPool* symtab,
int options, upb_Arena* arena, upb_Status* status) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
jsondec d;
if (size == 0) return true;
@ -4916,6 +4917,8 @@ void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) {
bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table,
const upb_MiniTableField* f,
upb_Message* map_entry_message, upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message));
// TODO: use a variant of upb_MiniTable_GetSubMessageTable() here.
const upb_MiniTable* map_entry_mini_table = upb_MiniTableSub_Message(
mini_table->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]);
@ -4967,6 +4970,7 @@ upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) {
}
void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
char* data = upb_Array_MutableDataPtr(arr);
const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
UPB_ASSERT(i < arr->UPB_PRIVATE(size));
@ -4974,6 +4978,7 @@ void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
}
bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
UPB_ASSERT(arena);
if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
arr, arr->UPB_PRIVATE(size) + 1, arena)) {
@ -4985,6 +4990,7 @@ bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
size_t count) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
char* data = upb_Array_MutableDataPtr(arr);
memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
@ -4992,6 +4998,7 @@ void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
UPB_ASSERT(arena);
UPB_ASSERT(i <= arr->UPB_PRIVATE(size));
UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count);
@ -5009,6 +5016,7 @@ bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
* |------------|XXXXXXXX|--------|
*/
void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const size_t end = i + count;
UPB_ASSERT(i <= end);
UPB_ASSERT(end <= arr->UPB_PRIVATE(size));
@ -5017,6 +5025,7 @@ void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
}
bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const size_t oldsize = arr->UPB_PRIVATE(size);
if (UPB_UNLIKELY(
!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) {
@ -5050,6 +5059,20 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity,
return true;
}
void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) {
if (upb_Array_IsFrozen(arr)) return;
UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr);
if (m) {
const size_t size = upb_Array_Size(arr);
for (size_t i = 0; i < size; i++) {
upb_MessageValue val = upb_Array_Get(arr, i);
upb_Message_Freeze((upb_Message*)val.msg_val, m);
}
}
}
#include <stddef.h>
#include <stdint.h>
@ -5079,6 +5102,7 @@ const upb_MiniTableExtension* upb_Message_FindExtensionByNumber(
}
#include <stdint.h>
#include <string.h>
@ -5177,6 +5201,20 @@ upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
return ret;
}
void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) {
if (upb_Map_IsFrozen(map)) return;
UPB_PRIVATE(_upb_Map_ShallowFreeze)(map);
if (m) {
size_t iter = kUpb_Map_Begin;
upb_MessageValue key, val;
while (upb_Map_Next(map, &key, &val, &iter)) {
upb_Message_Freeze((upb_Message*)val.msg_val, m);
}
}
}
// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
@ -5186,6 +5224,7 @@ upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
upb_strtable_init(&map->table, 4, a);
map->key_size = key_size;
map->val_size = value_size;
map->UPB_PRIVATE(is_frozen) = false;
return map;
}
@ -5349,22 +5388,24 @@ upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) {
bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data,
size_t len, upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false;
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len);
in->unknown_end += len;
return true;
}
void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
in->unknown_end = message_overhead;
}
}
const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
*len = in->unknown_end - message_overhead;
return (char*)(in + 1);
@ -5375,7 +5416,8 @@ const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
}
void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char);
#ifndef NDEBUG
@ -5399,6 +5441,73 @@ size_t upb_Message_ExtensionCount(const upb_Message* msg) {
return count;
}
void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
if (upb_Message_IsFrozen(msg)) return;
UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg);
// Base Fields.
const size_t field_count = upb_MiniTable_FieldCount(m);
for (size_t i = 0; i < field_count; i++) {
const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i);
const upb_MiniTable* m2 = upb_MiniTable_SubMessage(m, f);
switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
case kUpb_FieldMode_Array: {
upb_Array* arr = upb_Message_GetMutableArray(msg, f);
if (arr) upb_Array_Freeze(arr, m2);
break;
}
case kUpb_FieldMode_Map: {
upb_Map* map = upb_Message_GetMutableMap(msg, f);
if (map) {
const upb_MiniTableField* f2 = upb_MiniTable_MapValue(m2);
const upb_MiniTable* m3 = upb_MiniTable_SubMessage(m2, f2);
upb_Map_Freeze(map, m3);
}
break;
}
case kUpb_FieldMode_Scalar: {
if (m2) {
upb_Message* msg2 = upb_Message_GetMutableMessage(msg, f);
if (msg2) upb_Message_Freeze(msg2, m2);
}
break;
}
}
}
// Extensions.
size_t ext_count;
const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count);
for (size_t i = 0; i < ext_count; i++) {
const upb_MiniTableExtension* e = ext[i].ext;
const upb_MiniTableField* f = &e->UPB_PRIVATE(field);
const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e);
upb_MessageValue val;
memcpy(&val, &ext[i].data, sizeof(upb_MessageValue));
switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
case kUpb_FieldMode_Array: {
upb_Array* arr = (upb_Array*)val.array_val;
if (arr) upb_Array_Freeze(arr, m2);
break;
}
case kUpb_FieldMode_Map:
UPB_UNREACHABLE(); // Maps cannot be extensions.
break;
case kUpb_FieldMode_Scalar:
if (upb_MiniTableField_IsSubMessage(f)) {
upb_Message* msg2 = (upb_Message*)val.msg_val;
if (msg2) upb_Message_Freeze(msg2, m2);
}
break;
}
}
}
#include <string.h>
@ -8406,6 +8515,7 @@ upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
const upb_MiniTable* m,
const upb_ExtensionRegistry* extreg, int options,
upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Decoder decoder;
unsigned depth = (unsigned)options >> 16;
@ -11105,7 +11215,7 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)(
const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)(
const struct upb_Message* msg, size_t* count) {
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
*count = (in->size - in->ext_begin) / sizeof(upb_Extension);
return UPB_PTR_AT(in, in->ext_begin, void);
@ -11121,7 +11231,7 @@ upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(
if (ext) return ext;
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, sizeof(upb_Extension), a))
return NULL;
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
in->ext_begin -= sizeof(upb_Extension);
ext = UPB_PTR_AT(in, in->ext_begin, void);
memset(ext, 0, sizeof(upb_Extension));
@ -11144,7 +11254,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
upb_Arena* a) {
const size_t overhead = sizeof(upb_Message_Internal);
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (!in) {
// No internal data, allocate from scratch.
size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
@ -11154,7 +11264,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
in->size = size;
in->unknown_end = overhead;
in->ext_begin = size;
msg->internal = in;
UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
} else if (in->ext_begin - in->unknown_end < need) {
// Internal data is too small, reallocate.
size_t new_size = upb_Log2CeilingSize(in->size + need);
@ -11170,7 +11280,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
}
in->ext_begin = new_ext_begin;
in->size = new_size;
msg->internal = in;
UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
}
UPB_ASSERT(in->ext_begin - in->unknown_end >= need);

@ -842,13 +842,21 @@ struct upb_Array {
// 2 maps to elem size 8
// 3 maps to elem size 16
//
// Bit #2 contains the frozen/immutable flag (currently unimplemented).
// Bit #2 contains the frozen/immutable flag.
uintptr_t UPB_ONLYBITS(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_ShallowFreeze)(struct upb_Array* arr) {
arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Array_IsFrozen)(const struct upb_Array* arr) {
return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0;
}
UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array,
void* data, size_t lg2) {
UPB_ASSERT(lg2 != 1);
@ -898,6 +906,7 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size,
UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
size_t size, upb_Arena* arena) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
if (array->UPB_PRIVATE(capacity) < size)
return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena);
return true;
@ -906,6 +915,7 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
// Resize without initializing new elements.
UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
struct upb_Array* array, size_t size, upb_Arena* arena) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
UPB_ASSERT(size <= array->UPB_ONLYBITS(size) ||
arena); // Allow NULL arena when shrinking.
if (!UPB_PRIVATE(_upb_Array_Reserve)(array, size, arena)) return false;
@ -919,6 +929,7 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i,
const void* data,
size_t elem_size) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
UPB_ASSERT(i < array->UPB_ONLYBITS(size));
UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array));
char* arr_data = (char*)UPB_PRIVATE(_upb_Array_MutableDataPtr)(array);
@ -981,218 +992,6 @@ typedef union {
#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_INLINE size_t upb_Array_Size(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_Size)(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);
// Returns a mutating pointer to the given element, which must be within the
// array's current size.
UPB_API upb_MutableMessageValue upb_Array_GetMutable(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_INLINE const void* upb_Array_DataPtr(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_DataPtr)(arr);
}
// Returns mutable pointer to array data.
UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_MutableDataPtr)(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_BASE_INTERNAL_ENDIAN_H_
#define UPB_BASE_INTERNAL_ENDIAN_H_
#include <stdint.h>
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
UPB_INLINE bool upb_IsLittleEndian(void) {
const int x = 1;
return *(char*)&x == 1;
}
UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) {
if (upb_IsLittleEndian()) return val;
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) {
if (upb_IsLittleEndian()) return val;
const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32;
const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32));
return hi | lo;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */
#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
/*
** Our memory representation for parsing tables and messages themselves.
** Functions in this file are used by generated code and possibly reflection.
**
** The definitions in this file are internal to upb.
**/
#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
#include <stdlib.h>
#include <string.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_FIELD_H_
#define UPB_MINI_TABLE_FIELD_H_
@ -1547,6 +1346,86 @@ upb_MiniTableField_Type(const upb_MiniTableField* f) {
#endif /* UPB_MINI_TABLE_FIELD_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_
@ -1691,6 +1570,15 @@ UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(
return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret;
}
UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_SubMessage)(
const struct upb_MiniTable* m, const struct upb_MiniTableField* f) {
if (UPB_PRIVATE(_upb_MiniTableField_CType)(f) != kUpb_CType_Message) {
return NULL;
}
return UPB_PRIVATE(_upb_MiniTableSub_Message)(
m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]);
}
UPB_INLINE const struct upb_MiniTableEnum* UPB_PRIVATE(
_upb_MiniTable_GetSubEnumTable)(const struct upb_MiniTable* m,
const struct upb_MiniTableField* f) {
@ -1761,12 +1649,19 @@ UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m) {
return UPB_PRIVATE(_upb_MiniTable_FieldCount)(m);
}
// DEPRECATED: use upb_MiniTable_SubMessage() instead
// Returns the MiniTable for a message field, NULL if the field is unlinked.
UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
const upb_MiniTable* m, const upb_MiniTableField* f) {
return UPB_PRIVATE(_upb_MiniTable_GetSubMessageTable)(m, f);
}
// Returns the MiniTable for a message field if it is a submessage.
UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage(
const upb_MiniTable* m, const upb_MiniTableField* f) {
return UPB_PRIVATE(_upb_MiniTable_SubMessage)(m, f);
}
// Returns the MiniTableEnum for a message field, NULL if the field is unlinked.
UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
const upb_MiniTable* m, const upb_MiniTableField* f) {
@ -1820,6 +1715,148 @@ bool upb_MiniTable_NextOneofField(const upb_MiniTable* m,
#endif /* UPB_MINI_TABLE_MESSAGE_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_INLINE size_t upb_Array_Size(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_Size)(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);
// Returns a mutating pointer to the given element, which must be within the
// array's current size.
UPB_API upb_MutableMessageValue upb_Array_GetMutable(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_INLINE const void* upb_Array_DataPtr(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_DataPtr)(arr);
}
// Returns mutable pointer to array data.
UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_MutableDataPtr)(arr);
}
// Mark an array and all of its descendents as frozen/immutable.
// If the array elements are messages then |m| must point to the minitable for
// those messages. Otherwise |m| must be NULL.
UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m);
// Returns whether an array has been frozen.
UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_IsFrozen)(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_BASE_INTERNAL_ENDIAN_H_
#define UPB_BASE_INTERNAL_ENDIAN_H_
#include <stdint.h>
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
UPB_INLINE bool upb_IsLittleEndian(void) {
const int x = 1;
return *(char*)&x == 1;
}
UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) {
if (upb_IsLittleEndian()) return val;
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) {
if (upb_IsLittleEndian()) return val;
const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32;
const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32));
return hi | lo;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */
#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
/*
** Our memory representation for parsing tables and messages themselves.
** Functions in this file are used by generated code and possibly reflection.
**
** The definitions in this file are internal to upb.
**/
#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
#include <stdlib.h>
#include <string.h>
// Must be last.
#ifdef __cplusplus
@ -2340,6 +2377,7 @@ struct upb_Map {
// Strings are represented as '0' because they must be handled specially.
char key_size;
char val_size;
bool UPB_PRIVATE(is_frozen);
upb_strtable table;
};
@ -2348,6 +2386,14 @@ struct upb_Map {
extern "C" {
#endif
UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) {
map->UPB_PRIVATE(is_frozen) = true;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Map_IsFrozen)(const struct upb_Map* map) {
return map->UPB_PRIVATE(is_frozen);
}
// Converting between internal table representation and user values.
//
// _upb_map_tokey() and _upb_map_fromkey() are inverses.
@ -2405,11 +2451,15 @@ UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) {
}
UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(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_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(map));
upb_StringView k = _upb_map_tokey(key, key_size);
return upb_strtable_remove2(&map->table, k.data, k.size, val);
}
@ -2429,6 +2479,8 @@ 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_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(map));
upb_StringView strkey = _upb_map_tokey(key, key_size);
upb_value tabval = {0};
if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
@ -2516,13 +2568,44 @@ UPB_INLINE struct upb_Message* UPB_PRIVATE(
#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_
#define UPB_MESSAGE_INTERNAL_TYPES_H_
#include <stdint.h>
// Must be last.
#define UPB_OPAQUE(x) x##_opaque
struct upb_Message {
union {
struct upb_Message_Internal* internal;
uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen
double d; // Forces same size for 32-bit/64-bit builds
};
};
UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)(
struct upb_Message* msg) {
msg->UPB_OPAQUE(internal) |= 1ULL;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsFrozen)(
const struct upb_Message* msg) {
return (msg->UPB_OPAQUE(internal) & 1ULL) != 0;
}
UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)(
const struct upb_Message* msg) {
const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL;
return (struct upb_Message_Internal*)tmp;
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)(
struct upb_Message* msg, struct upb_Message_Internal* internal) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
msg->UPB_OPAQUE(internal) = (uintptr_t)internal;
}
#undef UPB_OPAQUE
#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */
// Must be last.
@ -2772,6 +2855,7 @@ UPB_INLINE void _upb_Message_GetExtensionField(
UPB_INLINE void _upb_Message_SetNonExtensionField(
struct upb_Message* msg, const upb_MiniTableField* field, const void* val) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
UPB_PRIVATE(_upb_Message_SetPresence)(msg, field);
UPB_PRIVATE(_upb_MiniTableField_DataCopy)
@ -2781,6 +2865,7 @@ UPB_INLINE void _upb_Message_SetNonExtensionField(
UPB_INLINE bool _upb_Message_SetExtensionField(
struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
const void* val, upb_Arena* a) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
UPB_ASSERT(a);
upb_Extension* ext =
UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, mt_ext, a);
@ -2792,11 +2877,13 @@ UPB_INLINE bool _upb_Message_SetExtensionField(
UPB_INLINE void UPB_PRIVATE(_upb_Message_Clear)(struct upb_Message* msg,
const upb_MiniTable* m) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
memset(msg, 0, m->UPB_PRIVATE(size));
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
struct upb_Message* msg, const upb_MiniTableField* f) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f);
} else if (upb_MiniTableField_IsInOneof(f)) {
@ -2811,7 +2898,8 @@ UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearExtension)(
struct upb_Message* msg, const upb_MiniTableExtension* e) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (!in) return;
const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension);
upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e);
@ -2961,6 +3049,16 @@ UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
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);
// Mark a map and all of its descendents as frozen/immutable.
// If the map values are messages then |m| must point to the minitable for
// those messages. Otherwise |m| must be NULL.
UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m);
// Returns whether a map has been frozen.
UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map) {
return UPB_PRIVATE(_upb_Map_IsFrozen)(map);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
@ -3004,6 +3102,14 @@ 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);
// Mark a message and all of its descendents as frozen/immutable.
UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m);
// Returns whether a message has been frozen.
UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg) {
return UPB_PRIVATE(_upb_Message_IsFrozen)(msg);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
@ -3398,6 +3504,11 @@ UPB_API_INLINE const upb_Message* upb_Message_GetMessage(
return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged);
}
UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage(
upb_Message* msg, const upb_MiniTableField* field) {
return (upb_Message*)upb_Message_GetMessage(msg, field, NULL);
}
// For internal use only; users cannot set tagged messages because only the
// parser and the message copier are allowed to directly create an empty
// message.

@ -3131,6 +3131,7 @@ static bool upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg,
bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
const upb_MessageDef* m, const upb_DefPool* symtab,
int options, upb_Arena* arena, upb_Status* status) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
jsondec d;
if (size == 0) return true;
@ -4430,6 +4431,8 @@ void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) {
bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table,
const upb_MiniTableField* f,
upb_Message* map_entry_message, upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message));
// TODO: use a variant of upb_MiniTable_GetSubMessageTable() here.
const upb_MiniTable* map_entry_mini_table = upb_MiniTableSub_Message(
mini_table->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]);
@ -4481,6 +4484,7 @@ upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) {
}
void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
char* data = upb_Array_MutableDataPtr(arr);
const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
UPB_ASSERT(i < arr->UPB_PRIVATE(size));
@ -4488,6 +4492,7 @@ void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
}
bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
UPB_ASSERT(arena);
if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
arr, arr->UPB_PRIVATE(size) + 1, arena)) {
@ -4499,6 +4504,7 @@ bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
size_t count) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
char* data = upb_Array_MutableDataPtr(arr);
memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
@ -4506,6 +4512,7 @@ void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
UPB_ASSERT(arena);
UPB_ASSERT(i <= arr->UPB_PRIVATE(size));
UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count);
@ -4523,6 +4530,7 @@ bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
* |------------|XXXXXXXX|--------|
*/
void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const size_t end = i + count;
UPB_ASSERT(i <= end);
UPB_ASSERT(end <= arr->UPB_PRIVATE(size));
@ -4531,6 +4539,7 @@ void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
}
bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
UPB_ASSERT(!upb_Array_IsFrozen(arr));
const size_t oldsize = arr->UPB_PRIVATE(size);
if (UPB_UNLIKELY(
!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) {
@ -4564,6 +4573,20 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity,
return true;
}
void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) {
if (upb_Array_IsFrozen(arr)) return;
UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr);
if (m) {
const size_t size = upb_Array_Size(arr);
for (size_t i = 0; i < size; i++) {
upb_MessageValue val = upb_Array_Get(arr, i);
upb_Message_Freeze((upb_Message*)val.msg_val, m);
}
}
}
#include <stddef.h>
#include <stdint.h>
@ -4593,6 +4616,7 @@ const upb_MiniTableExtension* upb_Message_FindExtensionByNumber(
}
#include <stdint.h>
#include <string.h>
@ -4691,6 +4715,20 @@ upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
return ret;
}
void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) {
if (upb_Map_IsFrozen(map)) return;
UPB_PRIVATE(_upb_Map_ShallowFreeze)(map);
if (m) {
size_t iter = kUpb_Map_Begin;
upb_MessageValue key, val;
while (upb_Map_Next(map, &key, &val, &iter)) {
upb_Message_Freeze((upb_Message*)val.msg_val, m);
}
}
}
// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
@ -4700,6 +4738,7 @@ upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
upb_strtable_init(&map->table, 4, a);
map->key_size = key_size;
map->val_size = value_size;
map->UPB_PRIVATE(is_frozen) = false;
return map;
}
@ -4863,22 +4902,24 @@ upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) {
bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data,
size_t len, upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false;
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len);
in->unknown_end += len;
return true;
}
void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
in->unknown_end = message_overhead;
}
}
const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
*len = in->unknown_end - message_overhead;
return (char*)(in + 1);
@ -4889,7 +4930,8 @@ const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
}
void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char);
#ifndef NDEBUG
@ -4913,6 +4955,73 @@ size_t upb_Message_ExtensionCount(const upb_Message* msg) {
return count;
}
void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
if (upb_Message_IsFrozen(msg)) return;
UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg);
// Base Fields.
const size_t field_count = upb_MiniTable_FieldCount(m);
for (size_t i = 0; i < field_count; i++) {
const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i);
const upb_MiniTable* m2 = upb_MiniTable_SubMessage(m, f);
switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
case kUpb_FieldMode_Array: {
upb_Array* arr = upb_Message_GetMutableArray(msg, f);
if (arr) upb_Array_Freeze(arr, m2);
break;
}
case kUpb_FieldMode_Map: {
upb_Map* map = upb_Message_GetMutableMap(msg, f);
if (map) {
const upb_MiniTableField* f2 = upb_MiniTable_MapValue(m2);
const upb_MiniTable* m3 = upb_MiniTable_SubMessage(m2, f2);
upb_Map_Freeze(map, m3);
}
break;
}
case kUpb_FieldMode_Scalar: {
if (m2) {
upb_Message* msg2 = upb_Message_GetMutableMessage(msg, f);
if (msg2) upb_Message_Freeze(msg2, m2);
}
break;
}
}
}
// Extensions.
size_t ext_count;
const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count);
for (size_t i = 0; i < ext_count; i++) {
const upb_MiniTableExtension* e = ext[i].ext;
const upb_MiniTableField* f = &e->UPB_PRIVATE(field);
const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e);
upb_MessageValue val;
memcpy(&val, &ext[i].data, sizeof(upb_MessageValue));
switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
case kUpb_FieldMode_Array: {
upb_Array* arr = (upb_Array*)val.array_val;
if (arr) upb_Array_Freeze(arr, m2);
break;
}
case kUpb_FieldMode_Map:
UPB_UNREACHABLE(); // Maps cannot be extensions.
break;
case kUpb_FieldMode_Scalar:
if (upb_MiniTableField_IsSubMessage(f)) {
upb_Message* msg2 = (upb_Message*)val.msg_val;
if (msg2) upb_Message_Freeze(msg2, m2);
}
break;
}
}
}
#include <string.h>
@ -7920,6 +8029,7 @@ upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
const upb_MiniTable* m,
const upb_ExtensionRegistry* extreg, int options,
upb_Arena* arena) {
UPB_ASSERT(!upb_Message_IsFrozen(msg));
upb_Decoder decoder;
unsigned depth = (unsigned)options >> 16;
@ -10619,7 +10729,7 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)(
const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)(
const struct upb_Message* msg, size_t* count) {
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (in) {
*count = (in->size - in->ext_begin) / sizeof(upb_Extension);
return UPB_PTR_AT(in, in->ext_begin, void);
@ -10635,7 +10745,7 @@ upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(
if (ext) return ext;
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, sizeof(upb_Extension), a))
return NULL;
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
in->ext_begin -= sizeof(upb_Extension);
ext = UPB_PTR_AT(in, in->ext_begin, void);
memset(ext, 0, sizeof(upb_Extension));
@ -10658,7 +10768,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
upb_Arena* a) {
const size_t overhead = sizeof(upb_Message_Internal);
upb_Message_Internal* in = msg->internal;
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (!in) {
// No internal data, allocate from scratch.
size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
@ -10668,7 +10778,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
in->size = size;
in->unknown_end = overhead;
in->ext_begin = size;
msg->internal = in;
UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
} else if (in->ext_begin - in->unknown_end < need) {
// Internal data is too small, reallocate.
size_t new_size = upb_Log2CeilingSize(in->size + need);
@ -10684,7 +10794,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
}
in->ext_begin = new_ext_begin;
in->size = new_size;
msg->internal = in;
UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
}
UPB_ASSERT(in->ext_begin - in->unknown_end >= need);

@ -844,13 +844,21 @@ struct upb_Array {
// 2 maps to elem size 8
// 3 maps to elem size 16
//
// Bit #2 contains the frozen/immutable flag (currently unimplemented).
// Bit #2 contains the frozen/immutable flag.
uintptr_t UPB_ONLYBITS(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_ShallowFreeze)(struct upb_Array* arr) {
arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Array_IsFrozen)(const struct upb_Array* arr) {
return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0;
}
UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array,
void* data, size_t lg2) {
UPB_ASSERT(lg2 != 1);
@ -900,6 +908,7 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size,
UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
size_t size, upb_Arena* arena) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
if (array->UPB_PRIVATE(capacity) < size)
return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena);
return true;
@ -908,6 +917,7 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Array_Reserve)(struct upb_Array* array,
// Resize without initializing new elements.
UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
struct upb_Array* array, size_t size, upb_Arena* arena) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
UPB_ASSERT(size <= array->UPB_ONLYBITS(size) ||
arena); // Allow NULL arena when shrinking.
if (!UPB_PRIVATE(_upb_Array_Reserve)(array, size, arena)) return false;
@ -921,6 +931,7 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i,
const void* data,
size_t elem_size) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Array_IsFrozen)(array));
UPB_ASSERT(i < array->UPB_ONLYBITS(size));
UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array));
char* arr_data = (char*)UPB_PRIVATE(_upb_Array_MutableDataPtr)(array);
@ -983,218 +994,6 @@ typedef union {
#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_INLINE size_t upb_Array_Size(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_Size)(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);
// Returns a mutating pointer to the given element, which must be within the
// array's current size.
UPB_API upb_MutableMessageValue upb_Array_GetMutable(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_INLINE const void* upb_Array_DataPtr(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_DataPtr)(arr);
}
// Returns mutable pointer to array data.
UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_MutableDataPtr)(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_BASE_INTERNAL_ENDIAN_H_
#define UPB_BASE_INTERNAL_ENDIAN_H_
#include <stdint.h>
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
UPB_INLINE bool upb_IsLittleEndian(void) {
const int x = 1;
return *(char*)&x == 1;
}
UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) {
if (upb_IsLittleEndian()) return val;
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) {
if (upb_IsLittleEndian()) return val;
const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32;
const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32));
return hi | lo;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */
#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
/*
** Our memory representation for parsing tables and messages themselves.
** Functions in this file are used by generated code and possibly reflection.
**
** The definitions in this file are internal to upb.
**/
#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
#include <stdlib.h>
#include <string.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_FIELD_H_
#define UPB_MINI_TABLE_FIELD_H_
@ -1549,6 +1348,86 @@ upb_MiniTableField_Type(const upb_MiniTableField* f) {
#endif /* UPB_MINI_TABLE_FIELD_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_
@ -1693,6 +1572,15 @@ UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(
return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret;
}
UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_SubMessage)(
const struct upb_MiniTable* m, const struct upb_MiniTableField* f) {
if (UPB_PRIVATE(_upb_MiniTableField_CType)(f) != kUpb_CType_Message) {
return NULL;
}
return UPB_PRIVATE(_upb_MiniTableSub_Message)(
m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]);
}
UPB_INLINE const struct upb_MiniTableEnum* UPB_PRIVATE(
_upb_MiniTable_GetSubEnumTable)(const struct upb_MiniTable* m,
const struct upb_MiniTableField* f) {
@ -1763,12 +1651,19 @@ UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m) {
return UPB_PRIVATE(_upb_MiniTable_FieldCount)(m);
}
// DEPRECATED: use upb_MiniTable_SubMessage() instead
// Returns the MiniTable for a message field, NULL if the field is unlinked.
UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
const upb_MiniTable* m, const upb_MiniTableField* f) {
return UPB_PRIVATE(_upb_MiniTable_GetSubMessageTable)(m, f);
}
// Returns the MiniTable for a message field if it is a submessage.
UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage(
const upb_MiniTable* m, const upb_MiniTableField* f) {
return UPB_PRIVATE(_upb_MiniTable_SubMessage)(m, f);
}
// Returns the MiniTableEnum for a message field, NULL if the field is unlinked.
UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
const upb_MiniTable* m, const upb_MiniTableField* f) {
@ -1822,6 +1717,148 @@ bool upb_MiniTable_NextOneofField(const upb_MiniTable* m,
#endif /* UPB_MINI_TABLE_MESSAGE_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_INLINE size_t upb_Array_Size(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_Size)(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);
// Returns a mutating pointer to the given element, which must be within the
// array's current size.
UPB_API upb_MutableMessageValue upb_Array_GetMutable(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_INLINE const void* upb_Array_DataPtr(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_DataPtr)(arr);
}
// Returns mutable pointer to array data.
UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_MutableDataPtr)(arr);
}
// Mark an array and all of its descendents as frozen/immutable.
// If the array elements are messages then |m| must point to the minitable for
// those messages. Otherwise |m| must be NULL.
UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m);
// Returns whether an array has been frozen.
UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr) {
return UPB_PRIVATE(_upb_Array_IsFrozen)(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_BASE_INTERNAL_ENDIAN_H_
#define UPB_BASE_INTERNAL_ENDIAN_H_
#include <stdint.h>
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
UPB_INLINE bool upb_IsLittleEndian(void) {
const int x = 1;
return *(char*)&x == 1;
}
UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) {
if (upb_IsLittleEndian()) return val;
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) {
if (upb_IsLittleEndian()) return val;
const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32;
const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32));
return hi | lo;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */
#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_
#define UPB_MESSAGE_INTERNAL_EXTENSION_H_
/*
** Our memory representation for parsing tables and messages themselves.
** Functions in this file are used by generated code and possibly reflection.
**
** The definitions in this file are internal to upb.
**/
#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
#include <stdlib.h>
#include <string.h>
// Must be last.
#ifdef __cplusplus
@ -2342,6 +2379,7 @@ struct upb_Map {
// Strings are represented as '0' because they must be handled specially.
char key_size;
char val_size;
bool UPB_PRIVATE(is_frozen);
upb_strtable table;
};
@ -2350,6 +2388,14 @@ struct upb_Map {
extern "C" {
#endif
UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) {
map->UPB_PRIVATE(is_frozen) = true;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Map_IsFrozen)(const struct upb_Map* map) {
return map->UPB_PRIVATE(is_frozen);
}
// Converting between internal table representation and user values.
//
// _upb_map_tokey() and _upb_map_fromkey() are inverses.
@ -2407,11 +2453,15 @@ UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) {
}
UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(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_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(map));
upb_StringView k = _upb_map_tokey(key, key_size);
return upb_strtable_remove2(&map->table, k.data, k.size, val);
}
@ -2431,6 +2481,8 @@ 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_ASSERT(!UPB_PRIVATE(_upb_Map_IsFrozen)(map));
upb_StringView strkey = _upb_map_tokey(key, key_size);
upb_value tabval = {0};
if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
@ -2518,13 +2570,44 @@ UPB_INLINE struct upb_Message* UPB_PRIVATE(
#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_
#define UPB_MESSAGE_INTERNAL_TYPES_H_
#include <stdint.h>
// Must be last.
#define UPB_OPAQUE(x) x##_opaque
struct upb_Message {
union {
struct upb_Message_Internal* internal;
uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen
double d; // Forces same size for 32-bit/64-bit builds
};
};
UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)(
struct upb_Message* msg) {
msg->UPB_OPAQUE(internal) |= 1ULL;
}
UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsFrozen)(
const struct upb_Message* msg) {
return (msg->UPB_OPAQUE(internal) & 1ULL) != 0;
}
UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)(
const struct upb_Message* msg) {
const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL;
return (struct upb_Message_Internal*)tmp;
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)(
struct upb_Message* msg, struct upb_Message_Internal* internal) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
msg->UPB_OPAQUE(internal) = (uintptr_t)internal;
}
#undef UPB_OPAQUE
#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */
// Must be last.
@ -2774,6 +2857,7 @@ UPB_INLINE void _upb_Message_GetExtensionField(
UPB_INLINE void _upb_Message_SetNonExtensionField(
struct upb_Message* msg, const upb_MiniTableField* field, const void* val) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
UPB_PRIVATE(_upb_Message_SetPresence)(msg, field);
UPB_PRIVATE(_upb_MiniTableField_DataCopy)
@ -2783,6 +2867,7 @@ UPB_INLINE void _upb_Message_SetNonExtensionField(
UPB_INLINE bool _upb_Message_SetExtensionField(
struct upb_Message* msg, const upb_MiniTableExtension* mt_ext,
const void* val, upb_Arena* a) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
UPB_ASSERT(a);
upb_Extension* ext =
UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, mt_ext, a);
@ -2794,11 +2879,13 @@ UPB_INLINE bool _upb_Message_SetExtensionField(
UPB_INLINE void UPB_PRIVATE(_upb_Message_Clear)(struct upb_Message* msg,
const upb_MiniTable* m) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
memset(msg, 0, m->UPB_PRIVATE(size));
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
struct upb_Message* msg, const upb_MiniTableField* f) {
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f);
} else if (upb_MiniTableField_IsInOneof(f)) {
@ -2813,7 +2900,8 @@ UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearExtension)(
struct upb_Message* msg, const upb_MiniTableExtension* e) {
upb_Message_Internal* in = msg->internal;
UPB_ASSERT(!UPB_PRIVATE(_upb_Message_IsFrozen)(msg));
upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
if (!in) return;
const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension);
upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e);
@ -2963,6 +3051,16 @@ UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
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);
// Mark a map and all of its descendents as frozen/immutable.
// If the map values are messages then |m| must point to the minitable for
// those messages. Otherwise |m| must be NULL.
UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m);
// Returns whether a map has been frozen.
UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map) {
return UPB_PRIVATE(_upb_Map_IsFrozen)(map);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
@ -3006,6 +3104,14 @@ 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);
// Mark a message and all of its descendents as frozen/immutable.
UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m);
// Returns whether a message has been frozen.
UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg) {
return UPB_PRIVATE(_upb_Message_IsFrozen)(msg);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
@ -3400,6 +3506,11 @@ UPB_API_INLINE const upb_Message* upb_Message_GetMessage(
return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged);
}
UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage(
upb_Message* msg, const upb_MiniTableField* field) {
return (upb_Message*)upb_Message_GetMessage(msg, field, NULL);
}
// For internal use only; users cannot set tagged messages because only the
// parser and the message copier are allowed to directly create an empty
// message.

Loading…
Cancel
Save