Move iteration APIs to headers, so they're inlined in loop calls PiperOrigin-RevId: 698497070
diff --git a/upb/message/compare.c b/upb/message/compare.c index 49ee33e..6963ea5 100644 --- a/upb/message/compare.c +++ b/upb/message/compare.c
@@ -142,8 +142,8 @@ upb_MessageValue val1; // Iterate over all extensions for msg1, and search msg2 for each extension. - size_t iter1 = kUpb_Extension_Begin; - while (UPB_PRIVATE(_upb_Message_NextExtension)(msg1, m, &e, &val1, &iter1)) { + size_t iter1 = kUpb_Message_ExtensionBegin; + while (upb_Message_NextExtension(msg1, &e, &val1, &iter1)) { const upb_Extension* ext2 = UPB_PRIVATE(_upb_Message_Getext)(msg2, e); if (!ext2) return false;
diff --git a/upb/message/compat.c b/upb/message/compat.c index 1bb2adc..0d79887 100644 --- a/upb/message/compat.c +++ b/upb/message/compat.c
@@ -10,36 +10,27 @@ #include <stddef.h> #include <stdint.h> -#include "upb/message/internal/extension.h" #include "upb/message/message.h" +#include "upb/message/value.h" #include "upb/mini_table/extension.h" // Must be last. #include "upb/port/def.inc" -bool upb_Message_NextExtension(const upb_Message* msg, - const upb_MiniTableExtension** result, - uintptr_t* iter) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - size_t i = *iter; - if (i >= count) { - return false; - *result = NULL; - } - *result = ext[i].ext; - *iter = i + 1; - return true; +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter) { + upb_MessageValue val; + return UPB_PRIVATE(_upb_Message_NextExtensionReverse)(msg, result, &val, + iter); } const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( const upb_Message* msg, uint32_t field_number) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - - for (; count--; ext++) { - const upb_MiniTableExtension* e = ext->ext; - if (upb_MiniTableExtension_Number(e) == field_number) return e; + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* result; + while (upb_Message_NextExtensionReverse(msg, &result, &iter)) { + if (upb_MiniTableExtension_Number(result) == field_number) return result; } return NULL; }
diff --git a/upb/message/compat.h b/upb/message/compat.h index 14ed2fe..7600ffa 100644 --- a/upb/message/compat.h +++ b/upb/message/compat.h
@@ -25,11 +25,10 @@ extern "C" { #endif -#define kUpb_Message_ExtensionBegin 0; - -bool upb_Message_NextExtension(const upb_Message* msg, - const upb_MiniTableExtension** result, - uintptr_t* iter); +// Same as upb_Message_NextExtension but iterates in reverse wire order +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter); // Returns the minitable with the given field number, or NULL on failure. const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( const upb_Message* msg, uint32_t field_number);
diff --git a/upb/message/internal/extension.c b/upb/message/internal/extension.c index f55253d..5eb41c4 100644 --- a/upb/message/internal/extension.c +++ b/upb/message/internal/extension.c
@@ -40,7 +40,7 @@ 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); + return UPB_PTR_AT(in, in->ext_begin, const upb_Extension); } else { *count = 0; return NULL;
diff --git a/upb/message/internal/iterator.c b/upb/message/internal/iterator.c index 82f2b37..b3ad76c 100644 --- a/upb/message/internal/iterator.c +++ b/upb/message/internal/iterator.c
@@ -12,10 +12,8 @@ #include "upb/message/accessors.h" #include "upb/message/array.h" #include "upb/message/internal/accessors.h" -#include "upb/message/internal/extension.h" #include "upb/message/map.h" #include "upb/message/message.h" -#include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" #include "upb/mini_table/message.h" @@ -58,21 +56,3 @@ return false; } - -bool UPB_PRIVATE(_upb_Message_NextExtension)( - const upb_Message* msg, const upb_MiniTable* m, - const upb_MiniTableExtension** out_e, upb_MessageValue* out_v, - size_t* iter) { - size_t count; - const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - size_t i = *iter; - - if (++i < count) { - *out_e = exts[i].ext; - *out_v = exts[i].data; - *iter = i; - return true; - } - - return false; -} \ No newline at end of file
diff --git a/upb/message/internal/iterator.h b/upb/message/internal/iterator.h index ad080db..484762d 100644 --- a/upb/message/internal/iterator.h +++ b/upb/message/internal/iterator.h
@@ -9,10 +9,10 @@ #define THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ #include <stddef.h> +#include <stdint.h> #include "upb/message/message.h" #include "upb/message/value.h" -#include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" #include "upb/mini_table/message.h" @@ -20,16 +20,10 @@ #include "upb/port/def.inc" #define kUpb_BaseField_Begin ((size_t)-1) -#define kUpb_Extension_Begin ((size_t)-1) - bool UPB_PRIVATE(_upb_Message_NextBaseField)(const upb_Message* msg, const upb_MiniTable* m, const upb_MiniTableField** out_f, upb_MessageValue* out_v, - size_t* iter); + uintptr_t* iter); -bool UPB_PRIVATE(_upb_Message_NextExtension)( - const upb_Message* msg, const upb_MiniTable* m, - const upb_MiniTableExtension** out_e, upb_MessageValue* out_v, - size_t* iter); #endif // THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_
diff --git a/upb/message/internal/map_sorter.h b/upb/message/internal/map_sorter.h index 33474d1..bd997bc 100644 --- a/upb/message/internal/map_sorter.h +++ b/upb/message/internal/map_sorter.h
@@ -18,6 +18,7 @@ #include "upb/message/internal/extension.h" #include "upb/message/internal/map.h" #include "upb/message/internal/map_entry.h" +#include "upb/message/internal/message.h" // Must be last. #include "upb/port/def.inc" @@ -80,7 +81,7 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, const struct upb_Map* map, _upb_sortedmap* sorted); -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, size_t count, _upb_sortedmap* sorted); #ifdef __cplusplus
diff --git a/upb/message/internal/message.h b/upb/message/internal/message.h index 2f7f0fa..c00b911 100644 --- a/upb/message/internal/message.h +++ b/upb/message/internal/message.h
@@ -15,11 +15,15 @@ #ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_ #define UPB_MESSAGE_INTERNAL_MESSAGE_H_ +#include <stdint.h> #include <stdlib.h> #include <string.h> +#include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/internal/extension.h" +#include "upb/message/internal/types.h" +#include "upb/mini_table/extension.h" #include "upb/mini_table/message.h" // Must be last. @@ -101,6 +105,68 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, upb_Arena* arena); +#define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 + +UPB_INLINE bool upb_Message_NextUnknown(const struct upb_Message* msg, + upb_StringView* data, uintptr_t* iter) { + const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in && *iter == kUpb_Message_UnknownBegin) { + size_t len = in->unknown_end - sizeof(upb_Message_Internal); + if (len != 0) { + data->size = len; + data->data = (const char*)(in + 1); + (*iter)++; + return true; + } + } + data->size = 0; + data->data = NULL; + return false; +} + +UPB_INLINE bool upb_Message_HasUnknown(const struct upb_Message* msg) { + upb_StringView data; + uintptr_t iter = kUpb_Message_UnknownBegin; + return upb_Message_NextUnknown(msg, &data, &iter); +} + +UPB_INLINE bool upb_Message_NextExtension(const struct upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order, so to iterate in wire order, + // we need to iterate backwards. + *out_e = exts[count - 1 - i].ext; + *out_v = exts[count - 1 - i].data; + *iter = i + 1; + return true; + } + + return false; +} + +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order + *out_e = exts[i].ext; + *out_v = exts[i].data; + *iter = i + 1; + return true; + } + + return false; +} + #ifdef __cplusplus } /* extern "C" */ #endif
diff --git a/upb/message/map_sorter.c b/upb/message/map_sorter.c index f0a4865..f0836ca 100644 --- a/upb/message/map_sorter.c +++ b/upb/message/map_sorter.c
@@ -14,8 +14,9 @@ #include "upb/base/internal/log2.h" #include "upb/base/string_view.h" #include "upb/mem/alloc.h" +#include "upb/message/internal/extension.h" +#include "upb/message/internal/message.h" #include "upb/message/map.h" -#include "upb/message/message.h" #include "upb/mini_table/extension.h" // Must be last. @@ -144,14 +145,15 @@ return a_num < b_num ? -1 : 1; } -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, size_t count, _upb_sortedmap* sorted) { if (!_upb_mapsorter_resize(s, sorted, count)) return false; + const upb_Extension* exts = + UPB_PTR_AT(in, in->ext_begin, const upb_Extension); for (size_t i = 0; i < count; i++) { s->entries[sorted->start + i] = &exts[i]; } - qsort(&s->entries[sorted->start], count, sizeof(*s->entries), _upb_mapsorter_cmpext); return true;
diff --git a/upb/message/message.c b/upb/message/message.c index 6ac5788..3a2d8e5 100644 --- a/upb/message/message.c +++ b/upb/message/message.c
@@ -30,8 +30,6 @@ // Must be last. #include "upb/port/def.inc" -static const size_t message_overhead = sizeof(upb_Message_Internal); - upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { return _upb_Message_New(m, a); } @@ -75,39 +73,14 @@ UPB_ASSERT(!upb_Message_IsFrozen(msg)); upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); if (in) { - in->unknown_end = message_overhead; + in->unknown_end = sizeof(upb_Message_Internal); } } -bool upb_Message_NextUnknown(const upb_Message* msg, upb_StringView* data, - uintptr_t* iter) { - const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in && *iter == kUpb_Message_UnknownBegin) { - size_t len = in->unknown_end - message_overhead; - if (len != 0) { - data->size = len; - data->data = (const char*)(in + 1); - (*iter)++; - return true; - } - } - data->size = 0; - data->data = NULL; - return false; -} - -bool upb_Message_HasUnknown(const upb_Message* msg) { - const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in) { - return in->unknown_end > message_overhead; - } - return false; -} - const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) { upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); if (in) { - *len = in->unknown_end - message_overhead; + *len = in->unknown_end - sizeof(upb_Message_Internal); return (char*)(in + 1); } else { *len = 0; @@ -185,17 +158,13 @@ } // 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; + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* e; + upb_MessageValue val; + while (upb_Message_NextExtension(msg, &e, &val, &iter)) { 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;
diff --git a/upb/message/message.h b/upb/message/message.h index a33cf32..f50cadb 100644 --- a/upb/message/message.h +++ b/upb/message/message.h
@@ -17,8 +17,11 @@ #include "upb/base/string_view.h" #include "upb/mem/arena.h" +#include "upb/message/array.h" +#include "upb/message/internal/extension.h" #include "upb/message/internal/message.h" #include "upb/message/internal/types.h" +#include "upb/mini_table/extension.h" #include "upb/mini_table/message.h" // Must be last. @@ -42,13 +45,15 @@ // while (upb_Message_NextUnknown(msg, &data, &iter)) { // // Use data // } +// Iterates in the order unknown fields were parsed. #define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 -bool upb_Message_NextUnknown(const upb_Message* msg, upb_StringView* data, - uintptr_t* iter); +UPB_INLINE bool upb_Message_NextUnknown(const upb_Message* msg, + upb_StringView* data, uintptr_t* iter); -bool upb_Message_HasUnknown(const upb_Message* msg); +UPB_INLINE bool upb_Message_HasUnknown(const upb_Message* msg); // Returns a reference to the message's unknown data. const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len); @@ -80,6 +85,17 @@ // Returns the number of extensions present in this message. size_t upb_Message_ExtensionCount(const upb_Message* msg); +// Iterates extensions in wire order +UPB_INLINE bool upb_Message_NextExtension(const upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter); + +// Iterates extensions in reverse wire order +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter); + // Mark a message and all of its descendents as frozen/immutable. UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m);
diff --git a/upb/text/debug_string.c b/upb/text/debug_string.c index eebf79e..c4b6609 100644 --- a/upb/text/debug_string.c +++ b/upb/text/debug_string.c
@@ -184,9 +184,9 @@ const upb_MiniTableExtension* ext; upb_MessageValue val_ext; - iter = kUpb_Extension_Begin; - while ( - UPB_PRIVATE(_upb_Message_NextExtension)(msg, mt, &ext, &val_ext, &iter)) { + iter = kUpb_Message_ExtensionBegin; + while (UPB_PRIVATE(_upb_Message_NextExtensionReverse)(msg, &ext, &val_ext, + &iter)) { const upb_MiniTableField* f = &ext->UPB_PRIVATE(field); // It is not sufficient to only pass |f| as we lose valuable information // about sub-messages. It is required that we pass |ext|.
diff --git a/upb/wire/encode.c b/upb/wire/encode.c index d3e68f1..b68ddc6 100644 --- a/upb/wire/encode.c +++ b/upb/wire/encode.c
@@ -12,6 +12,7 @@ #include <setjmp.h> #include <stdbool.h> #include <stdint.h> +#include <stdlib.h> #include <string.h> #include "upb/base/descriptor_constants.h" @@ -27,6 +28,7 @@ #include "upb/message/internal/map.h" #include "upb/message/internal/map_entry.h" #include "upb/message/internal/map_sorter.h" +#include "upb/message/internal/message.h" #include "upb/message/internal/tagged_ptr.h" #include "upb/message/map.h" #include "upb/message/message.h" @@ -523,32 +525,33 @@ } } -static void encode_msgset_item(upb_encstate* e, const upb_Extension* ext) { +static void encode_msgset_item(upb_encstate* e, + const upb_MiniTableExtension* ext, + const upb_MessageValue ext_val) { size_t size; encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup); - encode_message(e, ext->data.msg_val, - upb_MiniTableExtension_GetSubMessage(ext->ext), &size); + encode_message(e, ext_val.msg_val, upb_MiniTableExtension_GetSubMessage(ext), + &size); encode_varint(e, size); encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited); - encode_varint(e, upb_MiniTableExtension_Number(ext->ext)); + encode_varint(e, upb_MiniTableExtension_Number(ext)); encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint); encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup); } -static void encode_ext(upb_encstate* e, const upb_Extension* ext, - bool is_message_set) { +static void encode_ext(upb_encstate* e, const upb_MiniTableExtension* ext, + upb_MessageValue ext_val, bool is_message_set) { if (UPB_UNLIKELY(is_message_set)) { - encode_msgset_item(e, ext); + encode_msgset_item(e, ext, ext_val); } else { upb_MiniTableSubInternal sub; - if (upb_MiniTableField_IsSubMessage(&ext->ext->UPB_PRIVATE(field))) { - sub.UPB_PRIVATE(submsg) = &ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); + if (upb_MiniTableField_IsSubMessage(&ext->UPB_PRIVATE(field))) { + sub.UPB_PRIVATE(submsg) = &ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); } else { - sub.UPB_PRIVATE(subenum) = - ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); + sub.UPB_PRIVATE(subenum) = ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); } - encode_field(e, &ext->data.UPB_PRIVATE(ext_msg_val), &sub, - &ext->ext->UPB_PRIVATE(field)); + encode_field(e, &ext_val.UPB_PRIVATE(ext_msg_val), &sub, + &ext->UPB_PRIVATE(field)); } } @@ -568,7 +571,7 @@ size_t unknown_size = 0; uintptr_t iter = kUpb_Message_UnknownBegin; upb_StringView unknown; - // Need to write in reverse order, but list is single-linked; scan to + // Need to write in reverse order, but iteration is in-order; scan to // reserve capacity up front, then write in-order while (upb_Message_NextUnknown(msg, &unknown, &iter)) { unknown_size += unknown.size; @@ -585,24 +588,33 @@ } 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. */ - size_t ext_count; - const upb_Extension* ext = - UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count); - if (ext_count) { - if (e->options & kUpb_EncodeOption_Deterministic) { - _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->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); - } - _upb_mapsorter_popmap(&e->sorter, &sorted); - } else { - const upb_Extension* end = ext + ext_count; - for (; ext != end; ext++) { - encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + /* 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. */ + size_t ext_count = upb_Message_ExtensionCount(msg); + if (ext_count) { + if (e->options & kUpb_EncodeOption_Deterministic) { + _upb_sortedmap sorted; + if (!_upb_mapsorter_pushexts(&e->sorter, in, ext_count, &sorted)) { + // TODO: b/378744096 - handle alloc failure + } + const upb_Extension* ext; + while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { + encode_ext(e, ext->ext, ext->data, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + const upb_MiniTableExtension* ext; + upb_MessageValue ext_val; + uintptr_t iter = kUpb_Message_ExtensionBegin; + while (UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + msg, &ext, &ext_val, &iter)) { + encode_ext(e, ext, ext_val, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } } } }