|
|
|
@ -181,6 +181,12 @@ Error, UINTPTR_MAX is undefined |
|
|
|
|
|
|
|
|
|
#define UPB_PRIVATE(x) x##_dont_copy_me__upb_internal_use_only |
|
|
|
|
|
|
|
|
|
#ifdef UPB_ALLOW_PRIVATE_ACCESS__FOR_BITS_ONLY |
|
|
|
|
#define UPB_ONLYBITS(x) x |
|
|
|
|
#else |
|
|
|
|
#define UPB_ONLYBITS(x) UPB_PRIVATE(x) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* Configure whether fasttable is switched on or not. *************************/ |
|
|
|
|
|
|
|
|
|
#ifdef __has_attribute |
|
|
|
@ -5885,14 +5891,14 @@ upb_MapInsertStatus upb_Message_InsertMapEntry(upb_Map* map, |
|
|
|
|
upb_Message* map_entry_message, |
|
|
|
|
upb_Arena* arena) { |
|
|
|
|
// TODO: use a variant of upb_MiniTable_GetSubMessageTable() here.
|
|
|
|
|
const upb_MiniTable* map_entry_mini_table = |
|
|
|
|
upb_MiniTableSub_Message(mini_table->subs[f->UPB_PRIVATE(submsg_index)]); |
|
|
|
|
const upb_MiniTable* map_entry_mini_table = upb_MiniTableSub_Message( |
|
|
|
|
mini_table->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]); |
|
|
|
|
UPB_ASSERT(map_entry_mini_table); |
|
|
|
|
UPB_ASSERT(map_entry_mini_table->field_count == 2); |
|
|
|
|
UPB_ASSERT(map_entry_mini_table->UPB_PRIVATE(field_count) == 2); |
|
|
|
|
const upb_MiniTableField* map_entry_key_field = |
|
|
|
|
&map_entry_mini_table->fields[0]; |
|
|
|
|
&map_entry_mini_table->UPB_PRIVATE(fields)[0]; |
|
|
|
|
const upb_MiniTableField* map_entry_value_field = |
|
|
|
|
&map_entry_mini_table->fields[1]; |
|
|
|
|
&map_entry_mini_table->UPB_PRIVATE(fields)[1]; |
|
|
|
|
// Map key/value cannot have explicit defaults,
|
|
|
|
|
// hence assuming a zero default is valid.
|
|
|
|
|
upb_MessageValue default_val; |
|
|
|
@ -5975,7 +5981,7 @@ static bool upb_Clone_MessageValue(void* value, upb_CType value_type, |
|
|
|
|
case kUpb_CType_Message: { |
|
|
|
|
const upb_TaggedMessagePtr source = *(upb_TaggedMessagePtr*)value; |
|
|
|
|
bool is_empty = upb_TaggedMessagePtr_IsEmpty(source); |
|
|
|
|
if (is_empty) sub = &_kUpb_MiniTable_Empty; |
|
|
|
|
if (is_empty) sub = UPB_PRIVATE(_upb_MiniTable_Empty)(); |
|
|
|
|
UPB_ASSERT(source); |
|
|
|
|
upb_Message* clone = upb_Message_DeepClone( |
|
|
|
|
_upb_TaggedMessagePtr_GetMessage(source), sub, arena); |
|
|
|
@ -5998,7 +6004,8 @@ upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type, |
|
|
|
|
upb_MessageValue key, val; |
|
|
|
|
size_t iter = kUpb_Map_Begin; |
|
|
|
|
while (upb_Map_Next(map, &key, &val, &iter)) { |
|
|
|
|
const upb_MiniTableField* value_field = &map_entry_table->fields[1]; |
|
|
|
|
const upb_MiniTableField* value_field = |
|
|
|
|
&map_entry_table->UPB_PRIVATE(fields)[1]; |
|
|
|
|
const upb_MiniTable* value_sub = |
|
|
|
|
(value_field->UPB_PRIVATE(submsg_index) != kUpb_NoSub) |
|
|
|
|
? upb_MiniTable_GetSubMessageTable(map_entry_table, value_field) |
|
|
|
@ -6021,12 +6028,14 @@ static upb_Map* upb_Message_Map_DeepClone(const upb_Map* map, |
|
|
|
|
upb_Message* clone, |
|
|
|
|
upb_Arena* arena) { |
|
|
|
|
// TODO: use a variant of upb_MiniTable_GetSubMessageTable() here.
|
|
|
|
|
const upb_MiniTable* map_entry_table = |
|
|
|
|
upb_MiniTableSub_Message(mini_table->subs[f->UPB_PRIVATE(submsg_index)]); |
|
|
|
|
const upb_MiniTable* map_entry_table = upb_MiniTableSub_Message( |
|
|
|
|
mini_table->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)]); |
|
|
|
|
UPB_ASSERT(map_entry_table); |
|
|
|
|
|
|
|
|
|
const upb_MiniTableField* key_field = &map_entry_table->fields[0]; |
|
|
|
|
const upb_MiniTableField* value_field = &map_entry_table->fields[1]; |
|
|
|
|
const upb_MiniTableField* key_field = |
|
|
|
|
&map_entry_table->UPB_PRIVATE(fields)[0]; |
|
|
|
|
const upb_MiniTableField* value_field = |
|
|
|
|
&map_entry_table->UPB_PRIVATE(fields)[1]; |
|
|
|
|
|
|
|
|
|
upb_Map* cloned_map = upb_Map_DeepClone( |
|
|
|
|
map, upb_MiniTableField_CType(key_field), |
|
|
|
@ -6094,8 +6103,8 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, |
|
|
|
|
upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0); |
|
|
|
|
// Only copy message area skipping upb_Message_Internal.
|
|
|
|
|
memcpy(dst, src, mini_table->size); |
|
|
|
|
for (size_t i = 0; i < mini_table->field_count; ++i) { |
|
|
|
|
const upb_MiniTableField* field = &mini_table->fields[i]; |
|
|
|
|
for (size_t i = 0; i < mini_table->UPB_PRIVATE(field_count); ++i) { |
|
|
|
|
const upb_MiniTableField* field = &mini_table->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (upb_MiniTableField_IsScalar(field)) { |
|
|
|
|
switch (upb_MiniTableField_CType(field)) { |
|
|
|
|
case kUpb_CType_Message: { |
|
|
|
@ -6109,7 +6118,7 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, |
|
|
|
|
// decode status, or possible parse failure here.
|
|
|
|
|
bool is_empty = upb_TaggedMessagePtr_IsEmpty(tagged); |
|
|
|
|
const upb_MiniTable* sub_message_table = |
|
|
|
|
is_empty ? &_kUpb_MiniTable_Empty |
|
|
|
|
is_empty ? UPB_PRIVATE(_upb_MiniTable_Empty)() |
|
|
|
|
: upb_MiniTable_GetSubMessageTable(mini_table, field); |
|
|
|
|
upb_Message* dst_sub_message = |
|
|
|
|
upb_Message_DeepClone(sub_message, sub_message_table, arena); |
|
|
|
@ -7203,16 +7212,16 @@ static const char* upb_MtDecoder_ParseModifier(upb_MtDecoder* d, |
|
|
|
|
static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, |
|
|
|
|
upb_SubCounts sub_counts) { |
|
|
|
|
uint32_t total_count = sub_counts.submsg_count + sub_counts.subenum_count; |
|
|
|
|
size_t subs_bytes = sizeof(*d->table->subs) * total_count; |
|
|
|
|
size_t subs_bytes = sizeof(*d->table->UPB_PRIVATE(subs)) * total_count; |
|
|
|
|
upb_MiniTableSub* subs = upb_Arena_Malloc(d->arena, subs_bytes); |
|
|
|
|
upb_MdDecoder_CheckOutOfMemory(&d->base, subs); |
|
|
|
|
uint32_t i = 0; |
|
|
|
|
for (; i < sub_counts.submsg_count; i++) { |
|
|
|
|
subs[i].UPB_PRIVATE(submsg) = &_kUpb_MiniTable_Empty; |
|
|
|
|
subs[i].UPB_PRIVATE(submsg) = UPB_PRIVATE(_upb_MiniTable_Empty)(); |
|
|
|
|
} |
|
|
|
|
if (sub_counts.subenum_count) { |
|
|
|
|
upb_MiniTableField* f = d->fields; |
|
|
|
|
upb_MiniTableField* end_f = f + d->table->field_count; |
|
|
|
|
upb_MiniTableField* end_f = f + d->table->UPB_PRIVATE(field_count); |
|
|
|
|
for (; f < end_f; f++) { |
|
|
|
|
if (f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum) { |
|
|
|
|
f->UPB_PRIVATE(submsg_index) += sub_counts.submsg_count; |
|
|
|
@ -7222,7 +7231,7 @@ static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, |
|
|
|
|
subs[i].UPB_PRIVATE(subenum) = NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
d->table->subs = subs; |
|
|
|
|
d->table->UPB_PRIVATE(subs) = subs; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr, |
|
|
|
@ -7253,7 +7262,7 @@ static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr, |
|
|
|
|
ch <= kUpb_EncodedValue_MaxModifier) { |
|
|
|
|
ptr = upb_MtDecoder_ParseModifier(d, ptr, ch, last_field, &msg_modifiers); |
|
|
|
|
if (msg_modifiers & kUpb_MessageModifier_IsExtendable) { |
|
|
|
|
d->table->ext |= kUpb_ExtMode_Extendable; |
|
|
|
|
d->table->UPB_PRIVATE(ext) |= kUpb_ExtMode_Extendable; |
|
|
|
|
} |
|
|
|
|
} else if (ch == kUpb_EncodedValue_End) { |
|
|
|
|
if (!d->table) { |
|
|
|
@ -7263,7 +7272,7 @@ static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr, |
|
|
|
|
} else if (kUpb_EncodedValue_MinSkip <= ch && |
|
|
|
|
ch <= kUpb_EncodedValue_MaxSkip) { |
|
|
|
|
if (need_dense_below) { |
|
|
|
|
d->table->dense_below = d->table->field_count; |
|
|
|
|
d->table->UPB_PRIVATE(dense_below) = d->table->UPB_PRIVATE(field_count); |
|
|
|
|
need_dense_below = false; |
|
|
|
|
} |
|
|
|
|
uint32_t skip; |
|
|
|
@ -7278,7 +7287,7 @@ static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (need_dense_below) { |
|
|
|
|
d->table->dense_below = d->table->field_count; |
|
|
|
|
d->table->UPB_PRIVATE(dense_below) = d->table->UPB_PRIVATE(field_count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ptr; |
|
|
|
@ -7292,14 +7301,14 @@ static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data, |
|
|
|
|
upb_MdDecoder_CheckOutOfMemory(&d->base, d->fields); |
|
|
|
|
|
|
|
|
|
upb_SubCounts sub_counts = {0, 0}; |
|
|
|
|
d->table->field_count = 0; |
|
|
|
|
d->table->fields = d->fields; |
|
|
|
|
d->table->UPB_PRIVATE(field_count) = 0; |
|
|
|
|
d->table->UPB_PRIVATE(fields) = d->fields; |
|
|
|
|
upb_MtDecoder_Parse(d, data, len, d->fields, sizeof(*d->fields), |
|
|
|
|
&d->table->field_count, &sub_counts); |
|
|
|
|
&d->table->UPB_PRIVATE(field_count), &sub_counts); |
|
|
|
|
|
|
|
|
|
upb_Arena_ShrinkLast(d->arena, d->fields, sizeof(*d->fields) * len, |
|
|
|
|
sizeof(*d->fields) * d->table->field_count); |
|
|
|
|
d->table->fields = d->fields; |
|
|
|
|
sizeof(*d->fields) * d->table->UPB_PRIVATE(field_count)); |
|
|
|
|
d->table->UPB_PRIVATE(fields) = d->fields; |
|
|
|
|
upb_MtDecoder_AllocateSubs(d, sub_counts); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -7326,7 +7335,7 @@ int upb_MtDecoder_CompareFields(const void* _a, const void* _b) { |
|
|
|
|
|
|
|
|
|
static bool upb_MtDecoder_SortLayoutItems(upb_MtDecoder* d) { |
|
|
|
|
// Add items for all non-oneof fields (oneofs were already added).
|
|
|
|
|
int n = d->table->field_count; |
|
|
|
|
int n = d->table->UPB_PRIVATE(field_count); |
|
|
|
|
for (int i = 0; i < n; i++) { |
|
|
|
|
upb_MiniTableField* f = &d->fields[i]; |
|
|
|
|
if (f->offset >= kOneofBase) continue; |
|
|
|
@ -7350,27 +7359,29 @@ static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) { |
|
|
|
|
|
|
|
|
|
static void upb_MtDecoder_AssignHasbits(upb_MtDecoder* d) { |
|
|
|
|
upb_MiniTable* ret = d->table; |
|
|
|
|
int n = ret->field_count; |
|
|
|
|
int n = ret->UPB_PRIVATE(field_count); |
|
|
|
|
int last_hasbit = 0; // 0 cannot be used.
|
|
|
|
|
|
|
|
|
|
// First assign required fields, which must have the lowest hasbits.
|
|
|
|
|
for (int i = 0; i < n; i++) { |
|
|
|
|
upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i]; |
|
|
|
|
upb_MiniTableField* field = |
|
|
|
|
(upb_MiniTableField*)&ret->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (field->offset == kRequiredPresence) { |
|
|
|
|
field->presence = ++last_hasbit; |
|
|
|
|
} else if (field->offset == kNoPresence) { |
|
|
|
|
field->presence = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
ret->required_count = last_hasbit; |
|
|
|
|
|
|
|
|
|
if (ret->required_count > 63) { |
|
|
|
|
if (last_hasbit > 63) { |
|
|
|
|
upb_MdDecoder_ErrorJmp(&d->base, "Too many required fields"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ret->UPB_PRIVATE(required_count) = last_hasbit; |
|
|
|
|
|
|
|
|
|
// Next assign non-required hasbit fields.
|
|
|
|
|
for (int i = 0; i < n; i++) { |
|
|
|
|
upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i]; |
|
|
|
|
upb_MiniTableField* field = |
|
|
|
|
(upb_MiniTableField*)&ret->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (field->offset == kHasbitPresence) { |
|
|
|
|
field->presence = ++last_hasbit; |
|
|
|
|
} |
|
|
|
@ -7409,7 +7420,7 @@ static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) { |
|
|
|
|
while (true) { |
|
|
|
|
f->presence = ~item->offset; |
|
|
|
|
if (f->offset == kUpb_LayoutItem_IndexSentinel) break; |
|
|
|
|
UPB_ASSERT(f->offset - kOneofBase < d->table->field_count); |
|
|
|
|
UPB_ASSERT(f->offset - kOneofBase < d->table->UPB_PRIVATE(field_count)); |
|
|
|
|
f = &d->fields[f->offset - kOneofBase]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -7477,9 +7488,9 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, |
|
|
|
|
upb_MtDecoder_ParseMessage(d, data, len); |
|
|
|
|
upb_MtDecoder_AssignHasbits(d); |
|
|
|
|
|
|
|
|
|
if (UPB_UNLIKELY(d->table->field_count != 2)) { |
|
|
|
|
if (UPB_UNLIKELY(d->table->UPB_PRIVATE(field_count) != 2)) { |
|
|
|
|
upb_MdDecoder_ErrorJmp(&d->base, "%hu fields in map", |
|
|
|
|
d->table->field_count); |
|
|
|
|
d->table->UPB_PRIVATE(field_count)); |
|
|
|
|
UPB_UNREACHABLE(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -7490,8 +7501,8 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
upb_MtDecoder_ValidateEntryField(d, &d->table->fields[0], 1); |
|
|
|
|
upb_MtDecoder_ValidateEntryField(d, &d->table->fields[1], 2); |
|
|
|
|
upb_MtDecoder_ValidateEntryField(d, &d->table->UPB_PRIVATE(fields)[0], 1); |
|
|
|
|
upb_MtDecoder_ValidateEntryField(d, &d->table->UPB_PRIVATE(fields)[1], 2); |
|
|
|
|
|
|
|
|
|
// Map entries have a pre-determined layout, regardless of types.
|
|
|
|
|
// NOTE: sync with mini_table/message_internal.h.
|
|
|
|
@ -7503,7 +7514,7 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, |
|
|
|
|
|
|
|
|
|
// Map entries have a special bit set to signal it's a map entry, used in
|
|
|
|
|
// upb_MiniTable_SetSubMessage() below.
|
|
|
|
|
d->table->ext |= kUpb_ExtMode_IsMapEntry; |
|
|
|
|
d->table->UPB_PRIVATE(ext) |= kUpb_ExtMode_IsMapEntry; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data, |
|
|
|
@ -7515,11 +7526,11 @@ static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data, |
|
|
|
|
|
|
|
|
|
upb_MiniTable* ret = d->table; |
|
|
|
|
ret->size = 0; |
|
|
|
|
ret->field_count = 0; |
|
|
|
|
ret->ext = kUpb_ExtMode_IsMessageSet; |
|
|
|
|
ret->dense_below = 0; |
|
|
|
|
ret->table_mask = -1; |
|
|
|
|
ret->required_count = 0; |
|
|
|
|
ret->UPB_PRIVATE(field_count) = 0; |
|
|
|
|
ret->UPB_PRIVATE(ext) = kUpb_ExtMode_IsMessageSet; |
|
|
|
|
ret->UPB_PRIVATE(dense_below) = 0; |
|
|
|
|
ret->UPB_PRIVATE(table_mask) = -1; |
|
|
|
|
ret->UPB_PRIVATE(required_count) = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static upb_MiniTable* upb_MtDecoder_DoBuildMiniTableWithBuf( |
|
|
|
@ -7528,11 +7539,11 @@ static upb_MiniTable* upb_MtDecoder_DoBuildMiniTableWithBuf( |
|
|
|
|
upb_MdDecoder_CheckOutOfMemory(&decoder->base, decoder->table); |
|
|
|
|
|
|
|
|
|
decoder->table->size = 0; |
|
|
|
|
decoder->table->field_count = 0; |
|
|
|
|
decoder->table->ext = kUpb_ExtMode_NonExtendable; |
|
|
|
|
decoder->table->dense_below = 0; |
|
|
|
|
decoder->table->table_mask = -1; |
|
|
|
|
decoder->table->required_count = 0; |
|
|
|
|
decoder->table->UPB_PRIVATE(field_count) = 0; |
|
|
|
|
decoder->table->UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable; |
|
|
|
|
decoder->table->UPB_PRIVATE(dense_below) = 0; |
|
|
|
|
decoder->table->UPB_PRIVATE(table_mask) = -1; |
|
|
|
|
decoder->table->UPB_PRIVATE(required_count) = 0; |
|
|
|
|
|
|
|
|
|
// Strip off and verify the version tag.
|
|
|
|
|
if (!len--) goto done; |
|
|
|
@ -7625,7 +7636,7 @@ static const char* upb_MtDecoder_DoBuildMiniTableExtension( |
|
|
|
|
f->offset = 0; |
|
|
|
|
f->presence = 0; |
|
|
|
|
|
|
|
|
|
if (extendee->ext & kUpb_ExtMode_IsMessageSet) { |
|
|
|
|
if (extendee->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMessageSet) { |
|
|
|
|
// Extensions of MessageSet must be messages.
|
|
|
|
|
if (!upb_MiniTableField_IsSubMessage(f)) return NULL; |
|
|
|
|
|
|
|
|
@ -7701,17 +7712,18 @@ upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, |
|
|
|
|
bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, |
|
|
|
|
upb_MiniTableField* field, |
|
|
|
|
const upb_MiniTable* sub) { |
|
|
|
|
UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field && |
|
|
|
|
(uintptr_t)field < |
|
|
|
|
(uintptr_t)(table->fields + table->field_count)); |
|
|
|
|
UPB_ASSERT((uintptr_t)table->UPB_PRIVATE(fields) <= (uintptr_t)field && |
|
|
|
|
(uintptr_t)field < (uintptr_t)(table->UPB_PRIVATE(fields) + |
|
|
|
|
table->UPB_PRIVATE(field_count))); |
|
|
|
|
UPB_ASSERT(sub); |
|
|
|
|
|
|
|
|
|
const bool sub_is_map = sub->ext & kUpb_ExtMode_IsMapEntry; |
|
|
|
|
const bool sub_is_map = sub->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry; |
|
|
|
|
|
|
|
|
|
switch (field->UPB_PRIVATE(descriptortype)) { |
|
|
|
|
case kUpb_FieldType_Message: |
|
|
|
|
if (sub_is_map) { |
|
|
|
|
const bool table_is_map = table->ext & kUpb_ExtMode_IsMapEntry; |
|
|
|
|
const bool table_is_map = |
|
|
|
|
table->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry; |
|
|
|
|
if (UPB_UNLIKELY(table_is_map)) return false; |
|
|
|
|
|
|
|
|
|
field->mode = (field->mode & ~kUpb_FieldMode_Mask) | kUpb_FieldMode_Map; |
|
|
|
@ -7727,23 +7739,23 @@ bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
upb_MiniTableSub* table_sub = |
|
|
|
|
(void*)&table->subs[field->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
(void*)&table->UPB_PRIVATE(subs)[field->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
// TODO: Add this assert back once YouTube is updated to not call
|
|
|
|
|
// this function repeatedly.
|
|
|
|
|
// UPB_ASSERT(table_sub->submsg == &_kUpb_MiniTable_Empty);
|
|
|
|
|
// UPB_ASSERT(UPB_PRIVATE(_upb_MiniTable_IsEmpty)(table_sub->submsg));
|
|
|
|
|
*table_sub = upb_MiniTableSub_FromMessage(sub); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field, |
|
|
|
|
const upb_MiniTableEnum* sub) { |
|
|
|
|
UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field && |
|
|
|
|
(uintptr_t)field < |
|
|
|
|
(uintptr_t)(table->fields + table->field_count)); |
|
|
|
|
UPB_ASSERT((uintptr_t)table->UPB_PRIVATE(fields) <= (uintptr_t)field && |
|
|
|
|
(uintptr_t)field < (uintptr_t)(table->UPB_PRIVATE(fields) + |
|
|
|
|
table->UPB_PRIVATE(field_count))); |
|
|
|
|
UPB_ASSERT(sub); |
|
|
|
|
|
|
|
|
|
upb_MiniTableSub* table_sub = |
|
|
|
|
(void*)&table->subs[field->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
(void*)&table->UPB_PRIVATE(subs)[field->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
*table_sub = upb_MiniTableSub_FromEnum(sub); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -7753,8 +7765,8 @@ uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, |
|
|
|
|
uint32_t msg_count = 0; |
|
|
|
|
uint32_t enum_count = 0; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mt->field_count; i++) { |
|
|
|
|
const upb_MiniTableField* f = &mt->fields[i]; |
|
|
|
|
for (int i = 0; i < mt->UPB_PRIVATE(field_count); i++) { |
|
|
|
|
const upb_MiniTableField* f = &mt->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (upb_MiniTableField_CType(f) == kUpb_CType_Message) { |
|
|
|
|
*subs = f; |
|
|
|
|
++subs; |
|
|
|
@ -7762,8 +7774,8 @@ uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mt->field_count; i++) { |
|
|
|
|
const upb_MiniTableField* f = &mt->fields[i]; |
|
|
|
|
for (int i = 0; i < mt->UPB_PRIVATE(field_count); i++) { |
|
|
|
|
const upb_MiniTableField* f = &mt->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (upb_MiniTableField_CType(f) == kUpb_CType_Enum) { |
|
|
|
|
*subs = f; |
|
|
|
|
++subs; |
|
|
|
@ -7784,8 +7796,8 @@ bool upb_MiniTable_Link(upb_MiniTable* mt, const upb_MiniTable** sub_tables, |
|
|
|
|
uint32_t msg_count = 0; |
|
|
|
|
uint32_t enum_count = 0; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mt->field_count; i++) { |
|
|
|
|
upb_MiniTableField* f = (upb_MiniTableField*)&mt->fields[i]; |
|
|
|
|
for (int i = 0; i < mt->UPB_PRIVATE(field_count); i++) { |
|
|
|
|
upb_MiniTableField* f = (upb_MiniTableField*)&mt->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (upb_MiniTableField_CType(f) == kUpb_CType_Message) { |
|
|
|
|
const upb_MiniTable* sub = sub_tables[msg_count++]; |
|
|
|
|
if (msg_count > sub_table_count) return false; |
|
|
|
@ -7795,8 +7807,8 @@ bool upb_MiniTable_Link(upb_MiniTable* mt, const upb_MiniTable** sub_tables, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mt->field_count; i++) { |
|
|
|
|
upb_MiniTableField* f = (upb_MiniTableField*)&mt->fields[i]; |
|
|
|
|
for (int i = 0; i < mt->UPB_PRIVATE(field_count); i++) { |
|
|
|
|
upb_MiniTableField* f = (upb_MiniTableField*)&mt->UPB_PRIVATE(fields)[i]; |
|
|
|
|
if (upb_MiniTableField_IsClosedEnum(f)) { |
|
|
|
|
const upb_MiniTableEnum* sub = sub_enums[enum_count++]; |
|
|
|
|
if (enum_count > sub_enum_count) return false; |
|
|
|
@ -8219,21 +8231,21 @@ const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( |
|
|
|
|
// Must be last.
|
|
|
|
|
|
|
|
|
|
const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( |
|
|
|
|
const upb_MiniTable* t, uint32_t number) { |
|
|
|
|
const upb_MiniTable* m, uint32_t number) { |
|
|
|
|
const size_t i = ((size_t)number) - 1; // 0 wraps to SIZE_MAX
|
|
|
|
|
|
|
|
|
|
// Ideal case: index into dense fields
|
|
|
|
|
if (i < t->dense_below) { |
|
|
|
|
UPB_ASSERT(t->fields[i].number == number); |
|
|
|
|
return &t->fields[i]; |
|
|
|
|
if (i < m->UPB_PRIVATE(dense_below)) { |
|
|
|
|
UPB_ASSERT(m->UPB_PRIVATE(fields)[i].number == number); |
|
|
|
|
return &m->UPB_PRIVATE(fields)[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Slow case: binary search
|
|
|
|
|
int lo = t->dense_below; |
|
|
|
|
int hi = t->field_count - 1; |
|
|
|
|
int lo = m->UPB_PRIVATE(dense_below); |
|
|
|
|
int hi = m->UPB_PRIVATE(field_count) - 1; |
|
|
|
|
while (lo <= hi) { |
|
|
|
|
int mid = (lo + hi) / 2; |
|
|
|
|
uint32_t num = t->fields[mid].number; |
|
|
|
|
uint32_t num = m->UPB_PRIVATE(fields)[mid].number; |
|
|
|
|
if (num < number) { |
|
|
|
|
lo = mid + 1; |
|
|
|
|
continue; |
|
|
|
@ -8242,7 +8254,7 @@ const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( |
|
|
|
|
hi = mid - 1; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
return &t->fields[mid]; |
|
|
|
|
return &m->UPB_PRIVATE(fields)[mid]; |
|
|
|
|
} |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
@ -8252,8 +8264,9 @@ const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, |
|
|
|
|
if (UPB_UNLIKELY(!upb_MiniTableField_IsInOneof(f))) { |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
const upb_MiniTableField* ptr = &m->fields[0]; |
|
|
|
|
const upb_MiniTableField* end = &m->fields[m->field_count]; |
|
|
|
|
const upb_MiniTableField* ptr = &m->UPB_PRIVATE(fields)[0]; |
|
|
|
|
const upb_MiniTableField* end = |
|
|
|
|
&m->UPB_PRIVATE(fields)[m->UPB_PRIVATE(field_count)]; |
|
|
|
|
for (; ptr < end; ptr++) { |
|
|
|
|
if (ptr->presence == (*f).presence) { |
|
|
|
|
return ptr; |
|
|
|
@ -8265,7 +8278,8 @@ const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, |
|
|
|
|
bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, |
|
|
|
|
const upb_MiniTableField** f) { |
|
|
|
|
const upb_MiniTableField* ptr = *f; |
|
|
|
|
const upb_MiniTableField* end = &m->fields[m->field_count]; |
|
|
|
|
const upb_MiniTableField* end = |
|
|
|
|
&m->UPB_PRIVATE(fields)[m->UPB_PRIVATE(field_count)]; |
|
|
|
|
while (++ptr < end) { |
|
|
|
|
if (ptr->presence == (*f)->presence) { |
|
|
|
|
*f = ptr; |
|
|
|
@ -8276,15 +8290,20 @@ bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const struct upb_MiniTable _kUpb_MiniTable_Empty = { |
|
|
|
|
.subs = NULL, |
|
|
|
|
.fields = NULL, |
|
|
|
|
#include <stddef.h> |
|
|
|
|
|
|
|
|
|
// Must be last.
|
|
|
|
|
|
|
|
|
|
// A MiniTable for an empty message, used for unlinked sub-messages.
|
|
|
|
|
const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = { |
|
|
|
|
.UPB_PRIVATE(subs) = NULL, |
|
|
|
|
.UPB_PRIVATE(fields) = NULL, |
|
|
|
|
.size = 0, |
|
|
|
|
.field_count = 0, |
|
|
|
|
.ext = kUpb_ExtMode_NonExtendable, |
|
|
|
|
.dense_below = 0, |
|
|
|
|
.table_mask = -1, |
|
|
|
|
.required_count = 0, |
|
|
|
|
.UPB_PRIVATE(field_count) = 0, |
|
|
|
|
.UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable, |
|
|
|
|
.UPB_PRIVATE(dense_below) = 0, |
|
|
|
|
.UPB_PRIVATE(table_mask) = -1, |
|
|
|
|
.UPB_PRIVATE(required_count) = 0, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -9587,7 +9606,7 @@ const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f) { |
|
|
|
|
file, f->layout_index); |
|
|
|
|
} else { |
|
|
|
|
const upb_MiniTable* layout = upb_MessageDef_MiniTable(f->msgdef); |
|
|
|
|
return &layout->fields[f->layout_index]; |
|
|
|
|
return &layout->UPB_PRIVATE(fields)[f->layout_index]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -11794,7 +11813,7 @@ void _upb_MessageDef_CreateMiniTable(upb_DefBuilder* ctx, upb_MessageDef* m) { |
|
|
|
|
m->layout = _upb_MessageDef_MakeMiniTable(ctx, m); |
|
|
|
|
} else { |
|
|
|
|
m->layout = upb_MiniTableFile_Message(ctx->layout, ctx->msg_count++); |
|
|
|
|
UPB_ASSERT(m->field_count == m->layout->field_count); |
|
|
|
|
UPB_ASSERT(m->field_count == m->layout->UPB_PRIVATE(field_count)); |
|
|
|
|
|
|
|
|
|
// We don't need the result of this call, but it will assign layout_index
|
|
|
|
|
// for all the fields in O(n lg n) time.
|
|
|
|
@ -11830,9 +11849,9 @@ void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx, |
|
|
|
|
|
|
|
|
|
UPB_ASSERT(layout_index < m->field_count); |
|
|
|
|
upb_MiniTableField* mt_f = |
|
|
|
|
(upb_MiniTableField*)&m->layout->fields[layout_index]; |
|
|
|
|
(upb_MiniTableField*)&m->layout->UPB_PRIVATE(fields)[layout_index]; |
|
|
|
|
if (sub_m) { |
|
|
|
|
if (!mt->subs) { |
|
|
|
|
if (!mt->UPB_PRIVATE(subs)) { |
|
|
|
|
_upb_DefBuilder_Errf(ctx, "unexpected submsg for (%s)", m->full_name); |
|
|
|
|
} |
|
|
|
|
UPB_ASSERT(mt_f); |
|
|
|
@ -11852,8 +11871,9 @@ void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx, |
|
|
|
|
for (int i = 0; i < m->field_count; i++) { |
|
|
|
|
const upb_FieldDef* f = upb_MessageDef_Field(m, i); |
|
|
|
|
const int layout_index = _upb_FieldDef_LayoutIndex(f); |
|
|
|
|
UPB_ASSERT(layout_index < m->layout->field_count); |
|
|
|
|
const upb_MiniTableField* mt_f = &m->layout->fields[layout_index]; |
|
|
|
|
UPB_ASSERT(layout_index < m->layout->UPB_PRIVATE(field_count)); |
|
|
|
|
const upb_MiniTableField* mt_f = |
|
|
|
|
&m->layout->UPB_PRIVATE(fields)[layout_index]; |
|
|
|
|
UPB_ASSERT(upb_FieldDef_Type(f) == upb_MiniTableField_Type(mt_f)); |
|
|
|
|
UPB_ASSERT(upb_FieldDef_CType(f) == upb_MiniTableField_CType(mt_f)); |
|
|
|
|
UPB_ASSERT(upb_FieldDef_HasPresence(f) == |
|
|
|
@ -12630,6 +12650,8 @@ typedef union { |
|
|
|
|
// first argument, then we could just put them in mini_table/message.h as nice
|
|
|
|
|
// clean getters. But we don't have that so instead we gotta write these
|
|
|
|
|
// Frankenfunctions that take an array of subtables.
|
|
|
|
|
// TODO: Move these to mini_table/ anyway since there are other places
|
|
|
|
|
// that could use them.
|
|
|
|
|
|
|
|
|
|
// Returns the MiniTable corresponding to a given MiniTableField
|
|
|
|
|
// from an array of MiniTableSubs.
|
|
|
|
@ -12786,9 +12808,9 @@ static upb_Message* _upb_Decoder_NewSubMessage(upb_Decoder* d, |
|
|
|
|
upb_Message* msg = _upb_Message_New(subl, &d->arena); |
|
|
|
|
if (!msg) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); |
|
|
|
|
|
|
|
|
|
// Extensions should not be unlinked. A message extension should not be
|
|
|
|
|
// Extensions should not be unlinked. A message extension should not be
|
|
|
|
|
// registered until its sub-message type is available to be linked.
|
|
|
|
|
bool is_empty = subl == &_kUpb_MiniTable_Empty; |
|
|
|
|
bool is_empty = UPB_PRIVATE(_upb_MiniTable_IsEmpty)(subl); |
|
|
|
|
bool is_extension = field->mode & kUpb_LabelFlags_IsExtension; |
|
|
|
|
UPB_ASSERT(!(is_empty && is_extension)); |
|
|
|
|
|
|
|
|
@ -12807,7 +12829,8 @@ static upb_Message* _upb_Decoder_ReuseSubMessage( |
|
|
|
|
upb_TaggedMessagePtr tagged = *target; |
|
|
|
|
const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); |
|
|
|
|
UPB_ASSERT(subl); |
|
|
|
|
if (!upb_TaggedMessagePtr_IsEmpty(tagged) || subl == &_kUpb_MiniTable_Empty) { |
|
|
|
|
if (!upb_TaggedMessagePtr_IsEmpty(tagged) || |
|
|
|
|
UPB_PRIVATE(_upb_MiniTable_IsEmpty)(subl)) { |
|
|
|
|
return _upb_TaggedMessagePtr_GetMessage(tagged); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -13131,8 +13154,8 @@ upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, const upb_MiniTable* entry) { |
|
|
|
|
[kUpb_FieldType_SInt64] = 8, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const upb_MiniTableField* key_field = &entry->fields[0]; |
|
|
|
|
const upb_MiniTableField* val_field = &entry->fields[1]; |
|
|
|
|
const upb_MiniTableField* key_field = &entry->UPB_PRIVATE(fields)[0]; |
|
|
|
|
const upb_MiniTableField* val_field = &entry->UPB_PRIVATE(fields)[1]; |
|
|
|
|
char key_size = kSizeInMap[key_field->UPB_PRIVATE(descriptortype)]; |
|
|
|
|
char val_size = kSizeInMap[val_field->UPB_PRIVATE(descriptortype)]; |
|
|
|
|
UPB_ASSERT(key_field->offset == offsetof(upb_MapEntryData, k)); |
|
|
|
@ -13154,9 +13177,9 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, |
|
|
|
|
const upb_MiniTable* entry = _upb_MiniTableSubs_MessageByField(subs, field); |
|
|
|
|
|
|
|
|
|
UPB_ASSERT(entry); |
|
|
|
|
UPB_ASSERT(entry->field_count == 2); |
|
|
|
|
UPB_ASSERT(upb_MiniTableField_IsScalar(&entry->fields[0])); |
|
|
|
|
UPB_ASSERT(upb_MiniTableField_IsScalar(&entry->fields[1])); |
|
|
|
|
UPB_ASSERT(entry->UPB_PRIVATE(field_count) == 2); |
|
|
|
|
UPB_ASSERT(upb_MiniTableField_IsScalar(&entry->UPB_PRIVATE(fields)[0])); |
|
|
|
|
UPB_ASSERT(upb_MiniTableField_IsScalar(&entry->UPB_PRIVATE(fields)[1])); |
|
|
|
|
|
|
|
|
|
if (!map) { |
|
|
|
|
map = _upb_Decoder_CreateMap(d, entry); |
|
|
|
@ -13166,11 +13189,14 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, |
|
|
|
|
// Parse map entry.
|
|
|
|
|
memset(&ent, 0, sizeof(ent)); |
|
|
|
|
|
|
|
|
|
if (entry->fields[1].UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || |
|
|
|
|
entry->fields[1].UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group) { |
|
|
|
|
if (entry->UPB_PRIVATE(fields)[1].UPB_PRIVATE(descriptortype) == |
|
|
|
|
kUpb_FieldType_Message || |
|
|
|
|
entry->UPB_PRIVATE(fields)[1].UPB_PRIVATE(descriptortype) == |
|
|
|
|
kUpb_FieldType_Group) { |
|
|
|
|
// Create proactively to handle the case where it doesn't appear.
|
|
|
|
|
upb_TaggedMessagePtr msg; |
|
|
|
|
_upb_Decoder_NewSubMessage(d, entry->subs, &entry->fields[1], &msg); |
|
|
|
|
_upb_Decoder_NewSubMessage(d, entry->UPB_PRIVATE(subs), |
|
|
|
|
&entry->UPB_PRIVATE(fields)[1], &msg); |
|
|
|
|
ent.data.v.val = upb_value_uintptr(msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -13271,15 +13297,15 @@ static const char* _upb_Decoder_DecodeToSubMessage( |
|
|
|
|
UPB_NOINLINE |
|
|
|
|
const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr, |
|
|
|
|
const upb_Message* msg, |
|
|
|
|
const upb_MiniTable* l) { |
|
|
|
|
UPB_ASSERT(l->required_count); |
|
|
|
|
const upb_MiniTable* m) { |
|
|
|
|
UPB_ASSERT(m->UPB_PRIVATE(required_count)); |
|
|
|
|
if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) { |
|
|
|
|
return ptr; |
|
|
|
|
} |
|
|
|
|
uint64_t msg_head; |
|
|
|
|
memcpy(&msg_head, msg, 8); |
|
|
|
|
msg_head = _upb_BigEndian_Swap64(msg_head); |
|
|
|
|
if (upb_MiniTable_requiredmask(l) & ~msg_head) { |
|
|
|
|
if (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~msg_head) { |
|
|
|
|
d->missing_required = true; |
|
|
|
|
} |
|
|
|
|
return ptr; |
|
|
|
@ -13288,11 +13314,11 @@ const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr, |
|
|
|
|
UPB_FORCEINLINE |
|
|
|
|
static bool _upb_Decoder_TryFastDispatch(upb_Decoder* d, const char** ptr, |
|
|
|
|
upb_Message* msg, |
|
|
|
|
const upb_MiniTable* layout) { |
|
|
|
|
const upb_MiniTable* m) { |
|
|
|
|
#if UPB_FASTTABLE |
|
|
|
|
if (layout && layout->table_mask != (unsigned char)-1) { |
|
|
|
|
if (m && m->UPB_PRIVATE(table_mask) != (unsigned char)-1) { |
|
|
|
|
uint16_t tag = _upb_FastDecoder_LoadTag(*ptr); |
|
|
|
|
intptr_t table = decode_totable(layout); |
|
|
|
|
intptr_t table = decode_totable(m); |
|
|
|
|
*ptr = _upb_FastDecoder_TagDispatch(d, *ptr, msg, table, 0, tag); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -13448,30 +13474,30 @@ static const upb_MiniTableField* _upb_Decoder_FindField(upb_Decoder* d, |
|
|
|
|
if (t == NULL) return &none; |
|
|
|
|
|
|
|
|
|
size_t idx = ((size_t)field_number) - 1; // 0 wraps to SIZE_MAX
|
|
|
|
|
if (idx < t->dense_below) { |
|
|
|
|
if (idx < t->UPB_PRIVATE(dense_below)) { |
|
|
|
|
/* Fastest case: index into dense fields. */ |
|
|
|
|
goto found; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (t->dense_below < t->field_count) { |
|
|
|
|
if (t->UPB_PRIVATE(dense_below) < t->UPB_PRIVATE(field_count)) { |
|
|
|
|
/* Linear search non-dense fields. Resume scanning from last_field_index
|
|
|
|
|
* since fields are usually in order. */ |
|
|
|
|
size_t last = *last_field_index; |
|
|
|
|
for (idx = last; idx < t->field_count; idx++) { |
|
|
|
|
if (t->fields[idx].number == field_number) { |
|
|
|
|
for (idx = last; idx < t->UPB_PRIVATE(field_count); idx++) { |
|
|
|
|
if (t->UPB_PRIVATE(fields)[idx].number == field_number) { |
|
|
|
|
goto found; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (idx = t->dense_below; idx < last; idx++) { |
|
|
|
|
if (t->fields[idx].number == field_number) { |
|
|
|
|
for (idx = t->UPB_PRIVATE(dense_below); idx < last; idx++) { |
|
|
|
|
if (t->UPB_PRIVATE(fields)[idx].number == field_number) { |
|
|
|
|
goto found; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (d->extreg) { |
|
|
|
|
switch (t->ext) { |
|
|
|
|
switch (t->UPB_PRIVATE(ext)) { |
|
|
|
|
case kUpb_ExtMode_Extendable: { |
|
|
|
|
const upb_MiniTableExtension* ext = |
|
|
|
|
upb_ExtensionRegistry_Lookup(d->extreg, t, field_number); |
|
|
|
@ -13491,9 +13517,9 @@ static const upb_MiniTableField* _upb_Decoder_FindField(upb_Decoder* d, |
|
|
|
|
return &none; /* Unknown field. */ |
|
|
|
|
|
|
|
|
|
found: |
|
|
|
|
UPB_ASSERT(t->fields[idx].number == field_number); |
|
|
|
|
UPB_ASSERT(t->UPB_PRIVATE(fields)[idx].number == field_number); |
|
|
|
|
*last_field_index = idx; |
|
|
|
|
return &t->fields[idx]; |
|
|
|
|
return &t->UPB_PRIVATE(fields)[idx]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int _upb_Decoder_GetVarintOp(const upb_MiniTableField* field) { |
|
|
|
@ -13530,9 +13556,9 @@ static void _upb_Decoder_CheckUnlinked(upb_Decoder* d, const upb_MiniTable* mt, |
|
|
|
|
// If sub-message is not linked, treat as unknown.
|
|
|
|
|
if (field->mode & kUpb_LabelFlags_IsExtension) return; |
|
|
|
|
const upb_MiniTable* mt_sub = |
|
|
|
|
_upb_MiniTableSubs_MessageByField(mt->subs, field); |
|
|
|
|
_upb_MiniTableSubs_MessageByField(mt->UPB_PRIVATE(subs), field); |
|
|
|
|
if ((d->options & kUpb_DecodeOption_ExperimentalAllowUnlinked) || |
|
|
|
|
mt_sub != &_kUpb_MiniTable_Empty) { |
|
|
|
|
!UPB_PRIVATE(_upb_MiniTable_IsEmpty)(mt_sub)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#ifndef NDEBUG |
|
|
|
@ -13543,7 +13569,7 @@ static void _upb_Decoder_CheckUnlinked(upb_Decoder* d, const upb_MiniTable* mt, |
|
|
|
|
do { |
|
|
|
|
UPB_ASSERT(upb_MiniTableField_CType(oneof) == kUpb_CType_Message); |
|
|
|
|
const upb_MiniTableSub* oneof_sub = |
|
|
|
|
&mt->subs[oneof->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
&mt->UPB_PRIVATE(subs)[oneof->UPB_PRIVATE(submsg_index)]; |
|
|
|
|
UPB_ASSERT(!oneof_sub); |
|
|
|
|
} while (upb_MiniTable_NextOneofField(mt, &oneof)); |
|
|
|
|
} |
|
|
|
@ -13671,7 +13697,7 @@ static const char* _upb_Decoder_DecodeKnownField( |
|
|
|
|
upb_Decoder* d, const char* ptr, upb_Message* msg, |
|
|
|
|
const upb_MiniTable* layout, const upb_MiniTableField* field, int op, |
|
|
|
|
wireval* val) { |
|
|
|
|
const upb_MiniTableSub* subs = layout->subs; |
|
|
|
|
const upb_MiniTableSub* subs = layout->UPB_PRIVATE(subs); |
|
|
|
|
uint8_t mode = field->mode; |
|
|
|
|
|
|
|
|
|
if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) { |
|
|
|
@ -13825,7 +13851,7 @@ static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return UPB_UNLIKELY(layout && layout->required_count) |
|
|
|
|
return UPB_UNLIKELY(layout && layout->UPB_PRIVATE(required_count)) |
|
|
|
|
? _upb_Decoder_CheckRequired(d, ptr, msg, layout) |
|
|
|
|
: ptr; |
|
|
|
|
} |
|
|
|
@ -13961,9 +13987,9 @@ static const char* fastdecode_dispatch(UPB_PARSE_PARAMS) { |
|
|
|
|
switch (upb_EpsCopyInputStream_IsDoneStatus(&d->input, ptr, &overrun)) { |
|
|
|
|
case kUpb_IsDoneStatus_Done: |
|
|
|
|
*(uint32_t*)msg |= hasbits; // Sync hasbits.
|
|
|
|
|
const upb_MiniTable* l = decode_totablep(table); |
|
|
|
|
return UPB_UNLIKELY(l->required_count) |
|
|
|
|
? _upb_Decoder_CheckRequired(d, ptr, msg, l) |
|
|
|
|
const upb_MiniTable* m = decode_totablep(table); |
|
|
|
|
return UPB_UNLIKELY(m->UPB_PRIVATE(required_count)) |
|
|
|
|
? _upb_Decoder_CheckRequired(d, ptr, msg, m) |
|
|
|
|
: ptr; |
|
|
|
|
case kUpb_IsDoneStatus_NotDone: |
|
|
|
|
break; |
|
|
|
@ -14812,12 +14838,12 @@ static const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e, |
|
|
|
|
upb_Message** dst; \
|
|
|
|
|
uint32_t submsg_idx = (data >> 16) & 0xff; \
|
|
|
|
|
const upb_MiniTable* tablep = decode_totablep(table); \
|
|
|
|
|
const upb_MiniTable* subtablep = \
|
|
|
|
|
upb_MiniTableSub_Message(tablep->subs[submsg_idx]); \
|
|
|
|
|
const upb_MiniTable* subtablep = upb_MiniTableSub_Message( \
|
|
|
|
|
*UPB_PRIVATE(_upb_MiniTable_GetSubByIndex)(tablep, submsg_idx)); \
|
|
|
|
|
fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \
|
|
|
|
|
fastdecode_arr farr; \
|
|
|
|
|
\
|
|
|
|
|
if (subtablep->table_mask == (uint8_t)-1) { \
|
|
|
|
|
if (subtablep->UPB_PRIVATE(table_mask) == (uint8_t)-1) { \
|
|
|
|
|
d->depth++; \
|
|
|
|
|
RETURN_GENERIC("submessage doesn't have fast tables."); \
|
|
|
|
|
} \
|
|
|
|
@ -15082,7 +15108,7 @@ static void encode_TaggedMessagePtr(upb_encstate* e, |
|
|
|
|
upb_TaggedMessagePtr tagged, |
|
|
|
|
const upb_MiniTable* m, size_t* size) { |
|
|
|
|
if (upb_TaggedMessagePtr_IsEmpty(tagged)) { |
|
|
|
|
m = &_kUpb_MiniTable_Empty; |
|
|
|
|
m = UPB_PRIVATE(_upb_MiniTable_Empty)(); |
|
|
|
|
} |
|
|
|
|
encode_message(e, _upb_TaggedMessagePtr_GetMessage(tagged), m, size); |
|
|
|
|
} |
|
|
|
@ -15283,12 +15309,12 @@ static void encode_array(upb_encstate* e, const upb_Message* msg, |
|
|
|
|
static void encode_mapentry(upb_encstate* e, uint32_t number, |
|
|
|
|
const upb_MiniTable* layout, |
|
|
|
|
const upb_MapEntry* ent) { |
|
|
|
|
const upb_MiniTableField* key_field = &layout->fields[0]; |
|
|
|
|
const upb_MiniTableField* val_field = &layout->fields[1]; |
|
|
|
|
const upb_MiniTableField* key_field = &layout->UPB_PRIVATE(fields)[0]; |
|
|
|
|
const upb_MiniTableField* val_field = &layout->UPB_PRIVATE(fields)[1]; |
|
|
|
|
size_t pre_len = e->limit - e->ptr; |
|
|
|
|
size_t size; |
|
|
|
|
encode_scalar(e, &ent->data.v, layout->subs, val_field); |
|
|
|
|
encode_scalar(e, &ent->data.k, layout->subs, key_field); |
|
|
|
|
encode_scalar(e, &ent->data.v, layout->UPB_PRIVATE(subs), val_field); |
|
|
|
|
encode_scalar(e, &ent->data.k, layout->UPB_PRIVATE(subs), key_field); |
|
|
|
|
size = (e->limit - e->ptr) - pre_len; |
|
|
|
|
encode_varint(e, size); |
|
|
|
|
encode_tag(e, number, kUpb_WireType_Delimited); |
|
|
|
@ -15300,15 +15326,15 @@ static void encode_map(upb_encstate* e, const upb_Message* msg, |
|
|
|
|
const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*); |
|
|
|
|
const upb_MiniTable* layout = |
|
|
|
|
upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); |
|
|
|
|
UPB_ASSERT(layout->field_count == 2); |
|
|
|
|
UPB_ASSERT(layout->UPB_PRIVATE(field_count) == 2); |
|
|
|
|
|
|
|
|
|
if (map == NULL) return; |
|
|
|
|
|
|
|
|
|
if (e->options & kUpb_EncodeOption_Deterministic) { |
|
|
|
|
_upb_sortedmap sorted; |
|
|
|
|
_upb_mapsorter_pushmap(&e->sorter, |
|
|
|
|
layout->fields[0].UPB_PRIVATE(descriptortype), map, |
|
|
|
|
&sorted); |
|
|
|
|
_upb_mapsorter_pushmap( |
|
|
|
|
&e->sorter, layout->UPB_PRIVATE(fields)[0].UPB_PRIVATE(descriptortype), |
|
|
|
|
map, &sorted); |
|
|
|
|
upb_MapEntry ent; |
|
|
|
|
while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) { |
|
|
|
|
encode_mapentry(e, f->number, layout, &ent); |
|
|
|
@ -15410,11 +15436,12 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, |
|
|
|
|
const upb_MiniTable* m, size_t* size) { |
|
|
|
|
size_t pre_len = e->limit - e->ptr; |
|
|
|
|
|
|
|
|
|
if ((e->options & kUpb_EncodeOption_CheckRequired) && m->required_count) { |
|
|
|
|
if ((e->options & kUpb_EncodeOption_CheckRequired) && |
|
|
|
|
m->UPB_PRIVATE(required_count)) { |
|
|
|
|
uint64_t msg_head; |
|
|
|
|
memcpy(&msg_head, msg, 8); |
|
|
|
|
msg_head = _upb_BigEndian_Swap64(msg_head); |
|
|
|
|
if (upb_MiniTable_requiredmask(m) & ~msg_head) { |
|
|
|
|
if (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~msg_head) { |
|
|
|
|
encode_err(e, kUpb_EncodeStatus_MissingRequired); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -15428,7 +15455,7 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (m->ext != kUpb_ExtMode_NonExtendable) { |
|
|
|
|
if (m->UPB_PRIVATE(ext) != kUpb_ExtMode_NonExtendable) { |
|
|
|
|
/* Encode all extensions together. Unlike C++, we do not attempt to keep
|
|
|
|
|
* these in field number order relative to normal fields or even to each |
|
|
|
|
* other. */ |
|
|
|
@ -15439,25 +15466,26 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, |
|
|
|
|
_upb_sortedmap sorted; |
|
|
|
|
_upb_mapsorter_pushexts(&e->sorter, ext, ext_count, &sorted); |
|
|
|
|
while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { |
|
|
|
|
encode_ext(e, ext, m->ext == kUpb_ExtMode_IsMessageSet); |
|
|
|
|
encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); |
|
|
|
|
} |
|
|
|
|
_upb_mapsorter_popmap(&e->sorter, &sorted); |
|
|
|
|
} else { |
|
|
|
|
const upb_Message_Extension* end = ext + ext_count; |
|
|
|
|
for (; ext != end; ext++) { |
|
|
|
|
encode_ext(e, ext, m->ext == kUpb_ExtMode_IsMessageSet); |
|
|
|
|
encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (m->field_count) { |
|
|
|
|
const upb_MiniTableField* f = &m->fields[m->field_count]; |
|
|
|
|
const upb_MiniTableField* first = &m->fields[0]; |
|
|
|
|
if (m->UPB_PRIVATE(field_count)) { |
|
|
|
|
const upb_MiniTableField* f = |
|
|
|
|
&m->UPB_PRIVATE(fields)[m->UPB_PRIVATE(field_count)]; |
|
|
|
|
const upb_MiniTableField* first = &m->UPB_PRIVATE(fields)[0]; |
|
|
|
|
while (f != first) { |
|
|
|
|
f--; |
|
|
|
|
if (encode_shouldencode(e, msg, m->subs, f)) { |
|
|
|
|
encode_field(e, msg, m->subs, f); |
|
|
|
|
if (encode_shouldencode(e, msg, m->UPB_PRIVATE(subs), f)) { |
|
|
|
|
encode_field(e, msg, m->UPB_PRIVATE(subs), f); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -15598,3 +15626,4 @@ const char* _upb_WireReader_SkipGroup(const char* ptr, uint32_t tag, |
|
|
|
|
#undef UPB_ATOMIC |
|
|
|
|
#undef UPB_USE_C11_ATOMICS |
|
|
|
|
#undef UPB_PRIVATE |
|
|
|
|
#undef UPB_ONLYBITS |
|
|
|
|