Added staleness test to keep PHP copy of upb in sync with the upb repo (#10694)

* Updated to new upb.

* Updated to latest upb, which fixes 32-bit PHP!
pull/10705/head
Joshua Haberman 2 years ago committed by GitHub
parent 76c3e69146
commit 7755973302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      conformance/failure_list_php_c.txt
  2. 24
      php/BUILD.bazel
  3. 42
      php/ext/google/protobuf/message.c
  4. 20020
      php/ext/google/protobuf/php-upb.c
  5. 7645
      php/ext/google/protobuf/php-upb.h
  6. 4
      protobuf_deps.bzl
  7. 241
      ruby/ext/google/protobuf_c/ruby-upb.c
  8. 164
      ruby/ext/google/protobuf_c/ruby-upb.h

@ -1,5 +1,2 @@
Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
Required.Proto3.JsonInput.DurationNegativeSeconds.JsonOutput

@ -3,6 +3,7 @@
# See also code generation logic under /src/google/protobuf/compiler/php. # See also code generation logic under /src/google/protobuf/compiler/php.
load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix") load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
load("@upb//cmake:build_defs.bzl", "staleness_test")
load("//build_defs:internal_shell.bzl", "inline_sh_binary") load("//build_defs:internal_shell.bzl", "inline_sh_binary")
load("//conformance:defs.bzl", "conformance_test") load("//conformance:defs.bzl", "conformance_test")
@ -84,6 +85,29 @@ conformance_test(
}), }),
) )
genrule(
name = "copy_php_amalgamation_h",
srcs = ["@upb//:php-upb.h"],
outs = ["generated-in/ext/google/protobuf/php-upb.h"],
cmd = "cp $< $@",
)
genrule(
name = "copy_php_amalgamation_c",
srcs = ["@upb//:php-upb.c"],
outs = ["generated-in/ext/google/protobuf/php-upb.c"],
cmd = "cp $< $@",
)
staleness_test(
name = "test_amalgamation_staleness",
outs = [
"ext/google/protobuf/php-upb.h",
"ext/google/protobuf/php-upb.c",
],
generated_pattern = "generated-in/%s",
)
################################################################################ ################################################################################
# Distribution files # Distribution files
################################################################################ ################################################################################

@ -646,6 +646,25 @@ PHP_METHOD(Message, clear) {
upb_Message_Clear(intern->msg, intern->desc->msgdef); upb_Message_Clear(intern->msg, intern->desc->msgdef);
} }
static bool Message_checkEncodeStatus(upb_EncodeStatus status) {
switch (status) {
case kUpb_EncodeStatus_Ok:
return true;
case kUpb_EncodeStatus_OutOfMemory:
zend_throw_exception_ex(NULL, 0, "Out of memory");
return false;
case kUpb_EncodeStatus_MaxDepthExceeded:
zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
return false;
case kUpb_EncodeStatus_MissingRequired:
zend_throw_exception_ex(NULL, 0, "Missing required field");
return false;
default:
zend_throw_exception_ex(NULL, 0, "Unknown error encoding");
return false;
}
}
/** /**
* Message::mergeFrom() * Message::mergeFrom()
* *
@ -673,14 +692,9 @@ PHP_METHOD(Message, mergeFrom) {
// zend_parse_parameters(). // zend_parse_parameters().
PBPHP_ASSERT(from->desc == intern->desc); PBPHP_ASSERT(from->desc == intern->desc);
// TODO(haberman): use a temp arena for this once we can make upb_decode() // TODO(haberman): use a temp arena for this.
// copy strings. upb_EncodeStatus status = upb_Encode(from->msg, l, 0, arena, &pb, &size);
pb = upb_Encode(from->msg, l, 0, arena, &size); if (!Message_checkEncodeStatus(status)) return;
if (!pb) {
zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
return;
}
ok = upb_Decode(pb, size, intern->msg, l, NULL, 0, arena) == ok = upb_Decode(pb, size, intern->msg, l, NULL, 0, arena) ==
kUpb_DecodeStatus_Ok; kUpb_DecodeStatus_Ok;
@ -730,7 +744,9 @@ PHP_METHOD(Message, serializeToString) {
char *data; char *data;
size_t size; size_t size;
data = upb_Encode(intern->msg, l, 0, tmp_arena, &size); upb_EncodeStatus status =
upb_Encode(intern->msg, l, 0, tmp_arena, &data, &size);
if (!Message_checkEncodeStatus(status)) return;
if (!data) { if (!data) {
zend_throw_exception_ex(NULL, 0, "Error occurred during serialization"); zend_throw_exception_ex(NULL, 0, "Error occurred during serialization");
@ -1232,8 +1248,12 @@ PHP_METHOD(google_protobuf_Any, pack) {
msg = (Message*)Z_OBJ_P(val); msg = (Message*)Z_OBJ_P(val);
// Serialize and set value. // Serialize and set value.
value.data = upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->desc->msgdef), char* pb;
0, arena, &value.size); upb_EncodeStatus status =
upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->desc->msgdef), 0,
arena, &pb, &value.size);
if (!Message_checkEncodeStatus(status)) return;
value.data = pb;
Message_setval(intern, "value", StringVal(value)); Message_setval(intern, "value", StringVal(value));
// Set type url: type_url_prefix + fully_qualified_name // Set type url: type_url_prefix + fully_qualified_name

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -115,6 +115,6 @@ def protobuf_deps():
_github_archive( _github_archive(
name = "upb", name = "upb",
repo = "https://github.com/protocolbuffers/upb", repo = "https://github.com/protocolbuffers/upb",
commit = "82c6c4876161ccc6ce165121f925c56722abb926", commit = "32c6e9baab03d584b85390fdba789118f20613fc",
sha256 = "4c82bff4f790dbb5a11ec40b1fac44e7c95d9a63fd215a13aaf44cb27b10ac27", #sha256 = "4c82bff4f790dbb5a11ec40b1fac44e7c95d9a63fd215a13aaf44cb27b10ac27",
) )

@ -7307,10 +7307,6 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix,
bool ok = _upb_OneofDef_Insert(oneof, f, name.data, name.size, ctx->arena); bool ok = _upb_OneofDef_Insert(oneof, f, name.data, name.size, ctx->arena);
if (!ok) _upb_DefBuilder_OomErr(ctx); if (!ok) _upb_DefBuilder_OomErr(ctx);
} else if (f->proto3_optional_) {
_upb_DefBuilder_Errf(ctx,
"field with proto3_optional was not in a oneof (%s)",
f->full_name);
} }
UBP_DEF_SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto); UBP_DEF_SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto);
@ -7353,6 +7349,15 @@ static void _upb_FieldDef_CreateNotExt(
_upb_FieldDef_Create(ctx, prefix, field_proto, m, f); _upb_FieldDef_Create(ctx, prefix, field_proto, m, f);
f->is_extension_ = false; f->is_extension_ = false;
if (!google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
if (f->proto3_optional_) {
_upb_DefBuilder_Errf(
ctx,
"non-extension field (%s) with proto3_optional was not in a oneof",
f->full_name);
}
}
_upb_MessageDef_InsertField(ctx, m, f); _upb_MessageDef_InsertField(ctx, m, f);
if (!ctx->layout) return; if (!ctx->layout) return;
@ -12255,6 +12260,114 @@ upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
} }
// Must be last.
static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key,
void* b_key, size_t size) {
const upb_tabent* const* a = _a;
const upb_tabent* const* b = _b;
upb_StringView a_tabkey = upb_tabstrview((*a)->key);
upb_StringView b_tabkey = upb_tabstrview((*b)->key);
_upb_map_fromkey(a_tabkey, a_key, size);
_upb_map_fromkey(b_tabkey, b_key, size);
}
static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) {
int64_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
return a < b ? -1 : a > b;
}
static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) {
uint64_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
return a < b ? -1 : a > b;
}
static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) {
int32_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
return a < b ? -1 : a > b;
}
static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) {
uint32_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
return a < b ? -1 : a > b;
}
static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) {
bool a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
return a < b ? -1 : a > b;
}
static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) {
upb_StringView a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
size_t common_size = UPB_MIN(a.size, b.size);
int cmp = memcmp(a.data, b.data, common_size);
if (cmp) return -cmp;
return a.size < b.size ? -1 : a.size > b.size;
}
static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = {
[kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64,
[kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64,
[kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64,
[kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64,
[kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64,
[kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32,
[kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32,
[kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32,
[kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32,
[kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32,
[kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32,
[kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool,
[kUpb_FieldType_String] = _upb_mapsorter_cmpstr,
[kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr,
};
bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
const upb_Map* map, _upb_sortedmap* sorted) {
int map_size = _upb_Map_Size(map);
sorted->start = s->size;
sorted->pos = sorted->start;
sorted->end = sorted->start + map_size;
// Grow s->entries if necessary.
if (sorted->end > s->cap) {
s->cap = _upb_Log2CeilingSize(sorted->end);
s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
if (!s->entries) return false;
}
s->size = sorted->end;
// Copy non-empty entries from the table to s->entries.
upb_tabent const** dst = &s->entries[sorted->start];
const upb_tabent* src = map->table.t.entries;
const upb_tabent* end = src + upb_table_size(&map->table.t);
for (; src < end; src++) {
if (!upb_tabent_isempty(src)) {
*dst = src;
dst++;
}
}
UPB_ASSERT(dst == &s->entries[sorted->end]);
// Sort entries according to the key type.
qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries),
compar[key_type]);
return true;
}
#include <math.h> #include <math.h>
@ -12418,126 +12531,6 @@ upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
return map; return map;
} }
static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key,
void* b_key, size_t size) {
const upb_tabent* const* a = _a;
const upb_tabent* const* b = _b;
upb_StringView a_tabkey = upb_tabstrview((*a)->key);
upb_StringView b_tabkey = upb_tabstrview((*b)->key);
_upb_map_fromkey(a_tabkey, a_key, size);
_upb_map_fromkey(b_tabkey, b_key, size);
}
#define UPB_COMPARE_INTEGERS(a, b) ((a) < (b) ? -1 : ((a) == (b) ? 0 : 1))
static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) {
int64_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
return UPB_COMPARE_INTEGERS(a, b);
}
static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) {
uint64_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
return UPB_COMPARE_INTEGERS(a, b);
}
static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) {
int32_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
return UPB_COMPARE_INTEGERS(a, b);
}
static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) {
uint32_t a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
return UPB_COMPARE_INTEGERS(a, b);
}
static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) {
bool a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
return UPB_COMPARE_INTEGERS(a, b);
}
static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) {
upb_StringView a, b;
_upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
size_t common_size = UPB_MIN(a.size, b.size);
int cmp = memcmp(a.data, b.data, common_size);
if (cmp) return -cmp;
return UPB_COMPARE_INTEGERS(a.size, b.size);
}
#undef UPB_COMPARE_INTEGERS
bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
const upb_Map* map, _upb_sortedmap* sorted) {
int map_size = _upb_Map_Size(map);
sorted->start = s->size;
sorted->pos = sorted->start;
sorted->end = sorted->start + map_size;
/* Grow s->entries if necessary. */
if (sorted->end > s->cap) {
s->cap = _upb_Log2CeilingSize(sorted->end);
s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
if (!s->entries) return false;
}
s->size = sorted->end;
/* Copy non-empty entries from the table to s->entries. */
upb_tabent const** dst = &s->entries[sorted->start];
const upb_tabent* src = map->table.t.entries;
const upb_tabent* end = src + upb_table_size(&map->table.t);
for (; src < end; src++) {
if (!upb_tabent_isempty(src)) {
*dst = src;
dst++;
}
}
UPB_ASSERT(dst == &s->entries[sorted->end]);
/* Sort entries according to the key type. */
int (*compar)(const void*, const void*);
switch (key_type) {
case kUpb_FieldType_Int64:
case kUpb_FieldType_SFixed64:
case kUpb_FieldType_SInt64:
compar = _upb_mapsorter_cmpi64;
break;
case kUpb_FieldType_UInt64:
case kUpb_FieldType_Fixed64:
compar = _upb_mapsorter_cmpu64;
break;
case kUpb_FieldType_Int32:
case kUpb_FieldType_SInt32:
case kUpb_FieldType_SFixed32:
case kUpb_FieldType_Enum:
compar = _upb_mapsorter_cmpi32;
break;
case kUpb_FieldType_UInt32:
case kUpb_FieldType_Fixed32:
compar = _upb_mapsorter_cmpu32;
break;
case kUpb_FieldType_Bool:
compar = _upb_mapsorter_cmpbool;
break;
case kUpb_FieldType_String:
case kUpb_FieldType_Bytes:
compar = _upb_mapsorter_cmpstr;
break;
default:
UPB_UNREACHABLE();
}
qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
return true;
}
const float kUpb_FltInfinity = INFINITY; const float kUpb_FltInfinity = INFINITY;
const double kUpb_Infinity = INFINITY; const double kUpb_Infinity = INFINITY;

@ -699,9 +699,11 @@ typedef enum {
kUpb_FieldType_SFixed32 = 15, kUpb_FieldType_SFixed32 = 15,
kUpb_FieldType_SFixed64 = 16, kUpb_FieldType_SFixed64 = 16,
kUpb_FieldType_SInt32 = 17, kUpb_FieldType_SInt32 = 17,
kUpb_FieldType_SInt64 = 18 kUpb_FieldType_SInt64 = 18,
} upb_FieldType; } upb_FieldType;
#define kUpb_FieldType_SizeOf 19
#define kUpb_Map_Begin ((size_t)-1) #define kUpb_Map_Begin ((size_t)-1)
UPB_INLINE bool _upb_IsLittleEndian(void) { UPB_INLINE bool _upb_IsLittleEndian(void) {
@ -842,7 +844,6 @@ struct upb_Array {
uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
size_t size; /* The number of elements in the array. */ size_t size; /* The number of elements in the array. */
size_t capacity; /* Allocated storage. Measured in elements. */ size_t capacity; /* Allocated storage. Measured in elements. */
uint64_t junk;
}; };
UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) { UPB_INLINE const void* _upb_array_constptr(const upb_Array* arr) {
@ -867,8 +868,8 @@ UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) {
UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity, UPB_INLINE upb_Array* _upb_Array_New(upb_Arena* a, size_t init_capacity,
int elem_size_lg2) { int elem_size_lg2) {
const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), 8); const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN);
const size_t bytes = sizeof(upb_Array) + (init_capacity << elem_size_lg2); const size_t bytes = arr_size + (init_capacity << elem_size_lg2);
upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes); upb_Array* arr = (upb_Array*)upb_Arena_Malloc(a, bytes);
if (!arr) return NULL; if (!arr) return NULL;
arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2);
@ -1170,13 +1171,30 @@ extern "C" {
* reflection do not need to populate a upb_ExtensionRegistry directly. * reflection do not need to populate a upb_ExtensionRegistry directly.
*/ */
struct upb_ExtensionRegistry;
typedef struct upb_ExtensionRegistry upb_ExtensionRegistry; typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
/* Creates a upb_ExtensionRegistry in the given arena. The arena must outlive // Creates a upb_ExtensionRegistry in the given arena.
* any use of the extreg. */ // The arena must outlive any use of the extreg.
upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena); upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
typedef struct upb_MiniTable upb_MiniTable;
typedef struct upb_MiniTable_Extension upb_MiniTable_Extension;
// Adds the given extension info for message type |l| and field number |num|
// into the registry. Returns false if this message type and field number were
// already in the map, or if memory allocation fails.
bool _upb_extreg_add(upb_ExtensionRegistry* r,
const upb_MiniTable_Extension** e, size_t count);
// Looks up the extension (if any) defined for message type |l| and field
// number |num|. If an extension was found, copies the field info into |*ext|
// and returns true. Otherwise returns false.
const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
const upb_MiniTable* l,
uint32_t num);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
@ -1721,11 +1739,13 @@ struct upb_MiniTable {
_upb_FastTable_Entry fasttable[]; _upb_FastTable_Entry fasttable[];
}; };
typedef struct { typedef struct upb_MiniTable_Extension upb_MiniTable_Extension;
struct upb_MiniTable_Extension {
upb_MiniTable_Field field; upb_MiniTable_Field field;
const upb_MiniTable* extendee; const upb_MiniTable* extendee;
upb_MiniTable_Sub sub; /* NULL unless submessage or proto2 enum */ upb_MiniTable_Sub sub; /* NULL unless submessage or proto2 enum */
} upb_MiniTable_Extension; };
typedef struct { typedef struct {
const upb_MiniTable** msgs; const upb_MiniTable** msgs;
@ -1748,21 +1768,6 @@ UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
return ((1ULL << n) - 1) << 1; return ((1ULL << n) - 1) << 1;
} }
/** upb_ExtensionRegistry *****************************************************/
/* Adds the given extension info for message type |l| and field number |num|
* into the registry. Returns false if this message type and field number were
* already in the map, or if memory allocation fails. */
bool _upb_extreg_add(upb_ExtensionRegistry* r,
const upb_MiniTable_Extension** e, size_t count);
/* Looks up the extension (if any) defined for message type |l| and field
* number |num|. If an extension was found, copies the field info into |*ext|
* and returns true. Otherwise returns false. */
const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
const upb_MiniTable* l,
uint32_t num);
/** upb_Message ***************************************************************/ /** upb_Message ***************************************************************/
/* Internal members of a upb_Message that track unknown fields and/or /* Internal members of a upb_Message that track unknown fields and/or
@ -2158,53 +2163,6 @@ UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val,
} }
} }
/** _upb_mapsorter ************************************************************/
/* _upb_mapsorter sorts maps and provides ordered iteration over the entries.
* Since maps can be recursive (map values can be messages which contain other
* maps). _upb_mapsorter can contain a stack of maps. */
typedef struct {
upb_tabent const** entries;
int size;
int cap;
} _upb_mapsorter;
typedef struct {
int start;
int pos;
int end;
} _upb_sortedmap;
UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter* s) {
s->entries = NULL;
s->size = 0;
s->cap = 0;
}
UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter* s) {
if (s->entries) free(s->entries);
}
bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
const upb_Map* map, _upb_sortedmap* sorted);
UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s,
_upb_sortedmap* sorted) {
s->size = sorted->start;
}
UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
_upb_sortedmap* sorted, upb_MapEntry* ent) {
if (sorted->pos == sorted->end) return false;
const upb_tabent* tabent = s->entries[sorted->pos++];
upb_StringView key = upb_tabstrview(tabent->key);
_upb_map_fromkey(key, &ent->k, map->key_size);
upb_value val = {tabent->val.val};
_upb_map_fromvalue(val, &ent->v, map->val_size);
return true;
}
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
@ -7243,6 +7201,70 @@ bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a);
#endif /* UPB_REFLECTION_DESC_STATE_H_ */ #endif /* UPB_REFLECTION_DESC_STATE_H_ */
// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
#ifndef UPB_MAP_SORTER_H_
#define UPB_MAP_SORTER_H_
// Must be last.
#ifdef __cplusplus
extern "C" {
#endif
// _upb_mapsorter sorts maps and provides ordered iteration over the entries.
// Since maps can be recursive (map values can be messages which contain other
// maps), _upb_mapsorter can contain a stack of maps.
typedef struct {
upb_tabent const** entries;
int size;
int cap;
} _upb_mapsorter;
typedef struct {
int start;
int pos;
int end;
} _upb_sortedmap;
UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter* s) {
s->entries = NULL;
s->size = 0;
s->cap = 0;
}
UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter* s) {
if (s->entries) free(s->entries);
}
UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
_upb_sortedmap* sorted, upb_MapEntry* ent) {
if (sorted->pos == sorted->end) return false;
const upb_tabent* tabent = s->entries[sorted->pos++];
upb_StringView key = upb_tabstrview(tabent->key);
_upb_map_fromkey(key, &ent->k, map->key_size);
upb_value val = {tabent->val.val};
_upb_map_fromvalue(val, &ent->v, map->val_size);
return true;
}
UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s,
_upb_sortedmap* sorted) {
s->size = sorted->start;
}
bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
const upb_Map* map, _upb_sortedmap* sorted);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_MAP_SORTER_H_ */
/* See port_def.inc. This should #undef all macros #defined there. */ /* See port_def.inc. This should #undef all macros #defined there. */
#undef UPB_SIZE #undef UPB_SIZE

Loading…
Cancel
Save