diff options
Diffstat (limited to 'php/ext/google/protobuf/encode_decode.c')
-rw-r--r-- | php/ext/google/protobuf/encode_decode.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c index 93a5e9c4..7e2b3ae6 100644 --- a/php/ext/google/protobuf/encode_decode.c +++ b/php/ext/google/protobuf/encode_decode.c @@ -142,6 +142,23 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) { return hd_ofs; } +typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd, + const char* ptr, size_t len, + const upb_bufhandle* handle); + +typedef struct { + encodeunknown_handlerfunc handler; +} unknownfields_handlerdata_t; + +// Creates a handlerdata for unknown fields. +static const void *newunknownfieldshandlerdata(upb_handlers* h) { + unknownfields_handlerdata_t* hd = + (unknownfields_handlerdata_t*)malloc(sizeof(unknownfields_handlerdata_t)); + hd->handler = stringsink_string; + upb_handlers_addcleanup(h, hd, free); + return hd; +} + typedef struct { size_t ofs; const upb_msgdef *md; @@ -944,6 +961,24 @@ static void add_handlers_for_oneof_field(upb_handlers *h, upb_handlerattr_uninit(&attr); } +static bool add_unknown_handler(void* closure, const void* hd, const char* buf, + size_t size) { + encodeunknown_handlerfunc handler = + ((unknownfields_handlerdata_t*)hd)->handler; + + MessageHeader* msg = (MessageHeader*)closure; + stringsink* unknown = DEREF(message_data(msg), 0, stringsink*); + if (unknown == NULL) { + DEREF(message_data(msg), 0, stringsink*) = ALLOC(stringsink); + unknown = DEREF(message_data(msg), 0, stringsink*); + stringsink_init(unknown); + } + + handler(unknown, NULL, buf, size, NULL); + + return true; +} + static void add_handlers_for_message(const void* closure, upb_handlers* h) { const upb_msgdef* msgdef = upb_handlers_msgdef(h); @@ -967,6 +1002,10 @@ static void add_handlers_for_message(const void* closure, desc->layout = create_layout(desc->msgdef); } + upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr_sethandlerdata(&attr, newunknownfieldshandlerdata(h)); + upb_handlers_setunknown(h, add_unknown_handler, &attr); + for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { @@ -1278,6 +1317,11 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc, } } + stringsink* unknown = DEREF(message_data(msg), 0, stringsink*); + if (unknown != NULL) { + upb_sink_putunknown(sink, unknown->ptr, unknown->len); + } + upb_sink_endmsg(sink, &status); } |