diff --git a/upb/message/message.c b/upb/message/message.c index 5bb14e7591..daeeef1dcf 100644 --- a/upb/message/message.c +++ b/upb/message/message.c @@ -11,6 +11,7 @@ #include #include +#include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/accessors.h" #include "upb/message/array.h" @@ -52,6 +53,21 @@ void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) { } } +bool upb_Message_NextUnknown(const upb_Message* msg, upb_StringView* data, + uintptr_t* iter) { + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in && *iter == kUpb_Message_UnknownBegin) { + data->size = in->unknown_end - message_overhead; + data->data = (char*)(in + 1); + (*iter)++; + return true; + } else { + data->size = 0; + data->data = NULL; + 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) { diff --git a/upb/message/message.h b/upb/message/message.h index 50388fcb43..46f7d733dc 100644 --- a/upb/message/message.h +++ b/upb/message/message.h @@ -13,7 +13,9 @@ #define UPB_MESSAGE_MESSAGE_H_ #include +#include +#include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/internal/message.h" #include "upb/message/internal/types.h" @@ -31,6 +33,21 @@ extern "C" { // Creates a new message with the given mini_table on the given arena. UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena); +// +// Unknown data may be stored non-contiguously. Each segment stores a block of +// unknown fields. To iterate over segments: +// +// uintptr_t iter = kUpb_Message_UnknownBegin; +// upb_StringView data; +// while (upb_Message_NextUnknown(msg, &data, &iter)) { +// // Use data +// } + +#define kUpb_Message_UnknownBegin 0 + +bool upb_Message_NextUnknown(const upb_Message* msg, upb_StringView* data, + uintptr_t* iter); + // Returns a reference to the message's unknown data. const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);