Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.9 KiB
110 lines
3.9 KiB
1 year ago
|
// Protocol Buffers - Google's data interchange format
|
||
|
// Copyright 2023 Google LLC. All rights reserved.
|
||
|
//
|
||
1 year ago
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file or at
|
||
|
// https://developers.google.com/open-source/licenses/bsd
|
||
2 years ago
|
|
||
1 year ago
|
#include "upb/mini_table/compat.h"
|
||
1 year ago
|
|
||
1 year ago
|
#include "upb/base/descriptor_constants.h"
|
||
|
#include "upb/hash/common.h"
|
||
|
#include "upb/hash/int_table.h"
|
||
|
#include "upb/mem/arena.h"
|
||
|
#include "upb/mini_table/field.h"
|
||
|
#include "upb/mini_table/message.h"
|
||
2 years ago
|
|
||
|
// Must be last.
|
||
1 year ago
|
#include "upb/port/def.inc"
|
||
2 years ago
|
|
||
1 year ago
|
// 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->field_count != dst->field_count)
|
||
|
return kUpb_MiniTableEquals_NotEqual;
|
||
|
bool marked_src = false;
|
||
1 year ago
|
for (int i = 0; i < src->field_count; i++) {
|
||
|
const upb_MiniTableField* src_field = &src->fields[i];
|
||
|
const upb_MiniTableField* dst_field =
|
||
|
upb_MiniTable_FindFieldByNumber(dst, src_field->number);
|
||
|
|
||
|
if (upb_MiniTableField_CType(src_field) !=
|
||
1 year ago
|
upb_MiniTableField_CType(dst_field))
|
||
|
return false;
|
||
1 year ago
|
if (src_field->mode != dst_field->mode) return false;
|
||
|
if (src_field->offset != dst_field->offset) return false;
|
||
|
if (src_field->presence != dst_field->presence) return false;
|
||
|
if (src_field->UPB_PRIVATE(submsg_index) !=
|
||
1 year ago
|
dst_field->UPB_PRIVATE(submsg_index))
|
||
|
return kUpb_MiniTableEquals_NotEqual;
|
||
1 year ago
|
|
||
|
// Go no further if we are only checking for compatibility.
|
||
1 year ago
|
if (!table) continue;
|
||
2 years ago
|
|
||
1 year ago
|
if (upb_MiniTableField_CType(src_field) == kUpb_CType_Message) {
|
||
1 year ago
|
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;
|
||
|
}
|
||
|
}
|
||
1 year ago
|
const upb_MiniTable* sub_src =
|
||
|
upb_MiniTable_GetSubMessageTable(src, src_field);
|
||
|
const upb_MiniTable* sub_dst =
|
||
|
upb_MiniTable_GetSubMessageTable(dst, dst_field);
|
||
1 year ago
|
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;
|
||
|
}
|
||
|
}
|
||
1 year ago
|
}
|
||
|
}
|
||
|
}
|
||
1 year ago
|
return kUpb_MiniTableEquals_Equal;
|
||
2 years ago
|
}
|
||
|
|
||
1 year ago
|
bool upb_MiniTable_Compatible(const upb_MiniTable* src,
|
||
|
const upb_MiniTable* dst) {
|
||
1 year ago
|
return upb_deep_check(src, dst, NULL, NULL);
|
||
1 year ago
|
}
|
||
|
|
||
1 year ago
|
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;
|
||
1 year ago
|
}
|