|
|
|
@ -8420,23 +8420,6 @@ const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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, |
|
|
|
|
.UPB_PRIVATE(size) = 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, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <inttypes.h> |
|
|
|
|
#include <stddef.h> |
|
|
|
|
#include <stdint.h> |
|
|
|
@ -8504,6 +8487,106 @@ bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stddef.h> |
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Must be last.
|
|
|
|
|
|
|
|
|
|
// Checks if source and target mini table fields are identical.
|
|
|
|
|
//
|
|
|
|
|
// If the field is a sub message and sub messages are identical we record
|
|
|
|
|
// the association in table.
|
|
|
|
|
//
|
|
|
|
|
// Hashing the source sub message mini table and it's equivalent in the table
|
|
|
|
|
// stops recursing when a cycle is detected and instead just checks if the
|
|
|
|
|
// destination table is equal.
|
|
|
|
|
static upb_MiniTableEquals_Status upb_deep_check(const upb_MiniTable* src, |
|
|
|
|
const upb_MiniTable* dst, |
|
|
|
|
upb_inttable* table, |
|
|
|
|
upb_Arena** arena) { |
|
|
|
|
if (src->UPB_PRIVATE(field_count) != dst->UPB_PRIVATE(field_count)) |
|
|
|
|
return kUpb_MiniTableEquals_NotEqual; |
|
|
|
|
bool marked_src = false; |
|
|
|
|
for (int i = 0; i < upb_MiniTable_FieldCount(src); i++) { |
|
|
|
|
const upb_MiniTableField* src_field = upb_MiniTable_GetFieldByIndex(src, i); |
|
|
|
|
const upb_MiniTableField* dst_field = upb_MiniTable_FindFieldByNumber( |
|
|
|
|
dst, upb_MiniTableField_Number(src_field)); |
|
|
|
|
|
|
|
|
|
if (upb_MiniTableField_CType(src_field) != |
|
|
|
|
upb_MiniTableField_CType(dst_field)) |
|
|
|
|
return false; |
|
|
|
|
if (src_field->UPB_PRIVATE(mode) != dst_field->UPB_PRIVATE(mode)) |
|
|
|
|
return false; |
|
|
|
|
if (src_field->UPB_PRIVATE(offset) != dst_field->UPB_PRIVATE(offset)) |
|
|
|
|
return false; |
|
|
|
|
if (src_field->presence != dst_field->presence) return false; |
|
|
|
|
if (src_field->UPB_PRIVATE(submsg_index) != |
|
|
|
|
dst_field->UPB_PRIVATE(submsg_index)) |
|
|
|
|
return kUpb_MiniTableEquals_NotEqual; |
|
|
|
|
|
|
|
|
|
// Go no further if we are only checking for compatibility.
|
|
|
|
|
if (!table) continue; |
|
|
|
|
|
|
|
|
|
if (upb_MiniTableField_CType(src_field) == kUpb_CType_Message) { |
|
|
|
|
if (!*arena) { |
|
|
|
|
*arena = upb_Arena_New(); |
|
|
|
|
if (!upb_inttable_init(table, *arena)) { |
|
|
|
|
return kUpb_MiniTableEquals_OutOfMemory; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!marked_src) { |
|
|
|
|
marked_src = true; |
|
|
|
|
upb_value val; |
|
|
|
|
val.val = (uint64_t)dst; |
|
|
|
|
if (!upb_inttable_insert(table, (uintptr_t)src, val, *arena)) { |
|
|
|
|
return kUpb_MiniTableEquals_OutOfMemory; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
const upb_MiniTable* sub_src = |
|
|
|
|
upb_MiniTable_GetSubMessageTable(src, src_field); |
|
|
|
|
const upb_MiniTable* sub_dst = |
|
|
|
|
upb_MiniTable_GetSubMessageTable(dst, dst_field); |
|
|
|
|
if (sub_src != NULL) { |
|
|
|
|
upb_value cmp; |
|
|
|
|
if (upb_inttable_lookup(table, (uintptr_t)sub_src, &cmp)) { |
|
|
|
|
// We already compared this src before. Check if same dst.
|
|
|
|
|
if (cmp.val != (uint64_t)sub_dst) { |
|
|
|
|
return kUpb_MiniTableEquals_NotEqual; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Recurse if not already visited.
|
|
|
|
|
upb_MiniTableEquals_Status s = |
|
|
|
|
upb_deep_check(sub_src, sub_dst, table, arena); |
|
|
|
|
if (s != kUpb_MiniTableEquals_Equal) { |
|
|
|
|
return s; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return kUpb_MiniTableEquals_Equal; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_MiniTable_Compatible(const upb_MiniTable* src, |
|
|
|
|
const upb_MiniTable* dst) { |
|
|
|
|
return upb_deep_check(src, dst, NULL, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
upb_MiniTableEquals_Status upb_MiniTable_Equals(const upb_MiniTable* src, |
|
|
|
|
const upb_MiniTable* dst) { |
|
|
|
|
// Arena allocated on demand for hash table.
|
|
|
|
|
upb_Arena* arena = NULL; |
|
|
|
|
// Table to keep track of visited mini tables to guard against cycles.
|
|
|
|
|
upb_inttable table; |
|
|
|
|
upb_MiniTableEquals_Status status = upb_deep_check(src, dst, &table, &arena); |
|
|
|
|
if (arena) { |
|
|
|
|
upb_Arena_Free(arena); |
|
|
|
|
} |
|
|
|
|
return status; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Must be last.
|
|
|
|
|
|
|
|
|
@ -15792,6 +15875,23 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( |
|
|
|
|
return ptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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, |
|
|
|
|
.UPB_PRIVATE(size) = 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, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// This should #undef all macros #defined in def.inc
|
|
|
|
|
|
|
|
|
|
#undef UPB_SIZE |
|
|
|
|