From 3739d8bb302f56c9493be5dc1934b28e5c8fd6f2 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 27 Aug 2014 18:21:48 +0200 Subject: [PATCH] ocserv: updated to 0.8.4 Signed-off-by: Nikos Mavrogiannopoulos --- net/ocserv/Makefile | 4 +- ...ed-protobuf-s-path-to-align-with-pro.patch | 8774 ----------------- 2 files changed, 2 insertions(+), 8776 deletions(-) delete mode 100644 net/ocserv/patches/0001-corrected-included-protobuf-s-path-to-align-with-pro.patch diff --git a/net/ocserv/Makefile b/net/ocserv/Makefile index c850e498d..2cbf69ef4 100644 --- a/net/ocserv/Makefile +++ b/net/ocserv/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ocserv -PKG_VERSION:=0.8.3 +PKG_VERSION:=0.8.4 PKG_RELEASE:=1 PKG_BUILD_DIR :=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL :=ftp://ftp.infradead.org/pub/ocserv/ -PKG_MD5SUM:=fd74a172a34a9b4e0d52a43b098adbec +PKG_MD5SUM:=3eb452fddebda887eaa5f6412dab634c PKG_LICENSE:=GPLv3 PKG_LICENSE_FILES:=COPYING diff --git a/net/ocserv/patches/0001-corrected-included-protobuf-s-path-to-align-with-pro.patch b/net/ocserv/patches/0001-corrected-included-protobuf-s-path-to-align-with-pro.patch deleted file mode 100644 index 7de95f45a..000000000 --- a/net/ocserv/patches/0001-corrected-included-protobuf-s-path-to-align-with-pro.patch +++ /dev/null @@ -1,8774 +0,0 @@ -From 60bea96ccef5589bd8d35a438fdb9b3759852f36 Mon Sep 17 00:00:00 2001 -From: Nikos Mavrogiannopoulos -Date: Sun, 24 Aug 2014 08:14:11 +0200 -Subject: [PATCH] corrected included protobuf's path, to align with protobuf - 1.0.0 - ---- - configure.ac | 2 +- - src/Makefile.am | 2 +- - src/protobuf/google/protobuf-c/protobuf-c.c | 3272 --------------------------- - src/protobuf/google/protobuf-c/protobuf-c.h | 1079 --------- - src/protobuf/protobuf-c/protobuf-c.c | 3272 +++++++++++++++++++++++++++ - src/protobuf/protobuf-c/protobuf-c.h | 1079 +++++++++ - 6 files changed, 4353 insertions(+), 4353 deletions(-) - delete mode 100644 src/protobuf/google/protobuf-c/protobuf-c.c - delete mode 100644 src/protobuf/google/protobuf-c/protobuf-c.h - create mode 100644 src/protobuf/protobuf-c/protobuf-c.c - create mode 100644 src/protobuf/protobuf-c/protobuf-c.h - -diff --git a/configure.ac b/configure.ac -index 0515053..403fc45 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -78,7 +78,7 @@ if test "$test_for_protobuf" = yes;then - PKG_CHECK_MODULES([LIBPROTOBUF_C], [libprotobuf-c], - with_local_protobuf_c=no - , --[AC_LIB_HAVE_LINKFLAGS(protobuf-c,, [#include ], [protobuf_c_message_pack(0,0);]) -+[AC_LIB_HAVE_LINKFLAGS(protobuf-c,, [#include ], [protobuf_c_message_pack(0,0);]) - if test x$ac_cv_libprotobuf_c = xyes; then - AC_SUBST([LIBPROTOBUF_C_LIBS], [$LIBPROTOBUF_C]) - with_local_protobuf_c=no -diff --git a/src/Makefile.am b/src/Makefile.am -index 74acda4..69d3185 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -55,7 +55,7 @@ ocserv-args.h: ocserv-args.c - - PROTOBUF_SOURCES = - if LOCAL_PROTOBUF_C --PROTOBUF_SOURCES += protobuf/google/protobuf-c/protobuf-c.h protobuf/google/protobuf-c/protobuf-c.c -+PROTOBUF_SOURCES += protobuf/protobuf-c/protobuf-c.h protobuf/protobuf-c/protobuf-c.c - endif - - # Files common to ocserv and occtl. -diff --git a/src/protobuf/google/protobuf-c/protobuf-c.c b/src/protobuf/google/protobuf-c/protobuf-c.c -deleted file mode 100644 -index c7fb21d..0000000 ---- a/src/protobuf/google/protobuf-c/protobuf-c.c -+++ /dev/null -@@ -1,3272 +0,0 @@ --/* -- * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. -- * All rights reserved. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are -- * met: -- * -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * -- * * Redistributions in binary form must reproduce the above -- * copyright notice, this list of conditions and the following disclaimer -- * in the documentation and/or other materials provided with the -- * distribution. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- */ -- --/*! \file -- * Support library for `protoc-c` generated code. -- * -- * This file implements the public API used by the code generated -- * by `protoc-c`. -- * -- * \authors Dave Benson and the protobuf-c authors -- * -- * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. -- */ -- --/** -- * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math -- * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64). -- * -- * \todo Use size_t consistently. -- */ -- --#include /* for malloc, free */ --#include /* for strcmp, strlen, memcpy, memmove, memset */ -- --#include "protobuf-c.h" -- --#define TRUE 1 --#define FALSE 0 -- --#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0) -- --/** -- * \defgroup internal Internal functions and macros -- * -- * These are not exported by the library but are useful to developers working -- * on `libprotobuf-c` itself. -- */ -- --/** -- * \defgroup macros Utility macros for manipulating structures -- * -- * Macros and constants used to manipulate the base "classes" generated by -- * `protobuf-c`. They also define limits and check correctness. -- * -- * \ingroup internal -- * @{ -- */ -- --/** The maximum length of a 64-bit integer in varint encoding. */ --#define MAX_UINT64_ENCODED_SIZE 10 -- --#ifndef PROTOBUF_C_UNPACK_ERROR --# define PROTOBUF_C_UNPACK_ERROR(...) --#endif -- --/** -- * Internal `ProtobufCMessage` manipulation macro. -- * -- * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and -- * STRUCT_MEMBER_PTR(). -- */ --#define STRUCT_MEMBER_P(struct_p, struct_offset) \ -- ((void *) ((uint8_t *) (struct_p) + (struct_offset))) -- --/** -- * Return field in a `ProtobufCMessage` based on offset. -- * -- * Take a pointer to a `ProtobufCMessage` and find the field at the offset. -- * Cast it to the passed type. -- */ --#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ -- (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) -- --/** -- * Return field in a `ProtobufCMessage` based on offset. -- * -- * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast -- * it to a pointer to the passed type. -- */ --#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ -- ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) -- --/* Assertions for magic numbers. */ -- --#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ -- assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC) -- --#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ -- assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) -- --#define ASSERT_IS_MESSAGE(message) \ -- ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) -- --#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ -- assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC) -- --/**@}*/ -- --/* --- version --- */ -- --const char * --protobuf_c_version(void) --{ -- return PROTOBUF_C_VERSION; --} -- --uint32_t --protobuf_c_version_number(void) --{ -- return PROTOBUF_C_VERSION_NUMBER; --} -- --/* --- allocator --- */ -- --static void * --system_alloc(void *allocator_data, size_t size) --{ -- return malloc(size); --} -- --static void --system_free(void *allocator_data, void *data) --{ -- free(data); --} -- --static inline void * --do_alloc(ProtobufCAllocator *allocator, size_t size) --{ -- return allocator->alloc(allocator->allocator_data, size); --} -- --static inline void --do_free(ProtobufCAllocator *allocator, void *data) --{ -- if (data != NULL) -- allocator->free(allocator->allocator_data, data); --} -- --/* -- * This allocator uses the system's malloc() and free(). It is the default -- * allocator used if NULL is passed as the ProtobufCAllocator to an exported -- * function. -- */ --static ProtobufCAllocator protobuf_c__allocator = { -- .alloc = &system_alloc, -- .free = &system_free, -- .allocator_data = NULL, --}; -- --/* === buffer-simple === */ -- --void --protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, -- size_t len, const uint8_t *data) --{ -- ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; -- size_t new_len = simp->len + len; -- -- if (new_len > simp->alloced) { -- ProtobufCAllocator *allocator = simp->allocator; -- size_t new_alloced = simp->alloced * 2; -- uint8_t *new_data; -- -- if (allocator == NULL) -- allocator = &protobuf_c__allocator; -- while (new_alloced < new_len) -- new_alloced += new_alloced; -- new_data = do_alloc(allocator, new_alloced); -- if (!new_data) -- return; -- memcpy(new_data, simp->data, simp->len); -- if (simp->must_free_data) -- do_free(allocator, simp->data); -- else -- simp->must_free_data = TRUE; -- simp->data = new_data; -- simp->alloced = new_alloced; -- } -- memcpy(simp->data + simp->len, data, len); -- simp->len = new_len; --} -- --/** -- * \defgroup packedsz protobuf_c_message_get_packed_size() implementation -- * -- * Routines mainly used by protobuf_c_message_get_packed_size(). -- * -- * \ingroup internal -- * @{ -- */ -- --/** -- * Return the number of bytes required to store the tag for the field. Includes -- * 3 bits for the wire-type, and a single bit that denotes the end-of-tag. -- * -- * \param number -- * Field tag to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --get_tag_size(unsigned number) --{ -- if (number < (1 << 4)) { -- return 1; -- } else if (number < (1 << 11)) { -- return 2; -- } else if (number < (1 << 18)) { -- return 3; -- } else if (number < (1 << 25)) { -- return 4; -- } else { -- return 5; -- } --} -- --/** -- * Return the number of bytes required to store a variable-length unsigned -- * 32-bit integer in base-128 varint encoding. -- * -- * \param v -- * Value to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --uint32_size(uint32_t v) --{ -- if (v < (1 << 7)) { -- return 1; -- } else if (v < (1 << 14)) { -- return 2; -- } else if (v < (1 << 21)) { -- return 3; -- } else if (v < (1 << 28)) { -- return 4; -- } else { -- return 5; -- } --} -- --/** -- * Return the number of bytes required to store a variable-length signed 32-bit -- * integer in base-128 varint encoding. -- * -- * \param v -- * Value to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --int32_size(int32_t v) --{ -- if (v < 0) { -- return 10; -- } else if (v < (1 << 7)) { -- return 1; -- } else if (v < (1 << 14)) { -- return 2; -- } else if (v < (1 << 21)) { -- return 3; -- } else if (v < (1 << 28)) { -- return 4; -- } else { -- return 5; -- } --} -- --/** -- * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed -- * integer. -- * -- * \param v -- * Value to encode. -- * \return -- * ZigZag encoded integer. -- */ --static inline uint32_t --zigzag32(int32_t v) --{ -- if (v < 0) -- return ((uint32_t) (-v)) * 2 - 1; -- else -- return v * 2; --} -- --/** -- * Return the number of bytes required to store a signed 32-bit integer, -- * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128 -- * varint encoding. -- * -- * \param v -- * Value to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --sint32_size(int32_t v) --{ -- return uint32_size(zigzag32(v)); --} -- --/** -- * Return the number of bytes required to store a 64-bit unsigned integer in -- * base-128 varint encoding. -- * -- * \param v -- * Value to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --uint64_size(uint64_t v) --{ -- uint32_t upper_v = (uint32_t) (v >> 32); -- -- if (upper_v == 0) { -- return uint32_size((uint32_t) v); -- } else if (upper_v < (1 << 3)) { -- return 5; -- } else if (upper_v < (1 << 10)) { -- return 6; -- } else if (upper_v < (1 << 17)) { -- return 7; -- } else if (upper_v < (1 << 24)) { -- return 8; -- } else if (upper_v < (1U << 31)) { -- return 9; -- } else { -- return 10; -- } --} -- --/** -- * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed -- * integer. -- * -- * \param v -- * Value to encode. -- * \return -- * ZigZag encoded integer. -- */ --static inline uint64_t --zigzag64(int64_t v) --{ -- if (v < 0) -- return ((uint64_t) (-v)) * 2 - 1; -- else -- return v * 2; --} -- --/** -- * Return the number of bytes required to store a signed 64-bit integer, -- * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128 -- * varint encoding. -- * -- * \param v -- * Value to encode. -- * \return -- * Number of bytes required. -- */ --static inline size_t --sint64_size(int64_t v) --{ -- return uint64_size(zigzag64(v)); --} -- --/** -- * Calculate the serialized size of a single required message field, including -- * the space needed by the preceding tag. -- * -- * \param field -- * Field descriptor for member. -- * \param member -- * Field to encode. -- * \return -- * Number of bytes required. -- */ --static size_t --required_field_get_packed_size(const ProtobufCFieldDescriptor *field, -- const void *member) --{ -- size_t rv = get_tag_size(field->id); -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SINT32: -- return rv + sint32_size(*(const int32_t *) member); -- case PROTOBUF_C_TYPE_INT32: -- return rv + int32_size(*(const uint32_t *) member); -- case PROTOBUF_C_TYPE_UINT32: -- return rv + uint32_size(*(const uint32_t *) member); -- case PROTOBUF_C_TYPE_SINT64: -- return rv + sint64_size(*(const int64_t *) member); -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- return rv + uint64_size(*(const uint64_t *) member); -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- return rv + 4; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- return rv + 8; -- case PROTOBUF_C_TYPE_BOOL: -- return rv + 1; -- case PROTOBUF_C_TYPE_FLOAT: -- return rv + 4; -- case PROTOBUF_C_TYPE_DOUBLE: -- return rv + 8; -- case PROTOBUF_C_TYPE_ENUM: -- /* \todo Is this correct for negative-valued enums? */ -- return rv + uint32_size(*(const uint32_t *) member); -- case PROTOBUF_C_TYPE_STRING: { -- const char *str = *(char * const *) member; -- size_t len = str ? strlen(str) : 0; -- return rv + uint32_size(len) + len; -- } -- case PROTOBUF_C_TYPE_BYTES: { -- size_t len = ((const ProtobufCBinaryData *) member)->len; -- return rv + uint32_size(len) + len; -- } -- case PROTOBUF_C_TYPE_MESSAGE: { -- const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; -- size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0; -- return rv + uint32_size(subrv) + subrv; -- } -- } -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- return 0; --} -- --/** -- * Calculate the serialized size of a single optional message field, including -- * the space needed by the preceding tag. Returns 0 if the optional field isn't -- * set. -- * -- * \param field -- * Field descriptor for member. -- * \param has -- * True if the field exists, false if not. -- * \param member -- * Field to encode. -- * \return -- * Number of bytes required. -- */ --static size_t --optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, -- const protobuf_c_boolean *has, -- const void *member) --{ -- if (field->type == PROTOBUF_C_TYPE_MESSAGE || -- field->type == PROTOBUF_C_TYPE_STRING) -- { -- const void *ptr = *(const void * const *) member; -- if (ptr == NULL || ptr == field->default_value) -- return 0; -- } else { -- if (!*has) -- return 0; -- } -- return required_field_get_packed_size(field, member); --} -- --/** -- * Calculate the serialized size of repeated message fields, which may consist -- * of any number of values (including 0). Includes the space needed by the -- * preceding tags (as needed). -- * -- * \param field -- * Field descriptor for member. -- * \param count -- * Number of repeated field members. -- * \param member -- * Field to encode. -- * \return -- * Number of bytes required. -- */ --static size_t --repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field, -- size_t count, const void *member) --{ -- size_t header_size; -- size_t rv = 0; -- unsigned i; -- void *array = *(void * const *) member; -- -- if (count == 0) -- return 0; -- header_size = get_tag_size(field->id); -- if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) -- header_size *= count; -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SINT32: -- for (i = 0; i < count; i++) -- rv += sint32_size(((int32_t *) array)[i]); -- break; -- case PROTOBUF_C_TYPE_INT32: -- for (i = 0; i < count; i++) -- rv += int32_size(((uint32_t *) array)[i]); -- break; -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_ENUM: -- for (i = 0; i < count; i++) -- rv += uint32_size(((uint32_t *) array)[i]); -- break; -- case PROTOBUF_C_TYPE_SINT64: -- for (i = 0; i < count; i++) -- rv += sint64_size(((int64_t *) array)[i]); -- break; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- for (i = 0; i < count; i++) -- rv += uint64_size(((uint64_t *) array)[i]); -- break; -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- rv += 4 * count; -- break; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- rv += 8 * count; -- break; -- case PROTOBUF_C_TYPE_BOOL: -- rv += count; -- break; -- case PROTOBUF_C_TYPE_STRING: -- for (i = 0; i < count; i++) { -- size_t len = strlen(((char **) array)[i]); -- rv += uint32_size(len) + len; -- } -- break; -- case PROTOBUF_C_TYPE_BYTES: -- for (i = 0; i < count; i++) { -- size_t len = ((ProtobufCBinaryData *) array)[i].len; -- rv += uint32_size(len) + len; -- } -- break; -- case PROTOBUF_C_TYPE_MESSAGE: -- for (i = 0; i < count; i++) { -- size_t len = protobuf_c_message_get_packed_size( -- ((ProtobufCMessage **) array)[i]); -- rv += uint32_size(len) + len; -- } -- break; -- } -- -- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) -- header_size += uint32_size(rv); -- return header_size + rv; --} -- --/** -- * Calculate the serialized size of an unknown field, i.e. one that is passed -- * through mostly uninterpreted. This is required for forward compatibility if -- * new fields are added to the message descriptor. -- * -- * \param field -- * Unknown field type. -- * \return -- * Number of bytes required. -- */ --static inline size_t --unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field) --{ -- return get_tag_size(field->tag) + field->len; --} -- --/**@}*/ -- --/* -- * Calculate the serialized size of the message. -- */ --size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) --{ -- unsigned i; -- size_t rv = 0; -- -- ASSERT_IS_MESSAGE(message); -- for (i = 0; i < message->descriptor->n_fields; i++) { -- const ProtobufCFieldDescriptor *field = -- message->descriptor->fields + i; -- const void *member = -- ((const char *) message) + field->offset; -- const void *qmember = -- ((const char *) message) + field->quantifier_offset; -- -- if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -- rv += required_field_get_packed_size(field, member); -- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -- rv += optional_field_get_packed_size(field, qmember, member); -- } else { -- rv += repeated_field_get_packed_size( -- field, -- *(const size_t *) qmember, -- member -- ); -- } -- } -- for (i = 0; i < message->n_unknown_fields; i++) -- rv += unknown_field_get_packed_size(&message->unknown_fields[i]); -- return rv; --} -- --/** -- * \defgroup pack protobuf_c_message_pack() implementation -- * -- * Routines mainly used by protobuf_c_message_pack(). -- * -- * \ingroup internal -- * @{ -- */ -- --/** -- * Pack an unsigned 32-bit integer in base-128 varint encoding and return the -- * number of bytes written, which must be 5 or less. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --uint32_pack(uint32_t value, uint8_t *out) --{ -- unsigned rv = 0; -- -- if (value >= 0x80) { -- out[rv++] = value | 0x80; -- value >>= 7; -- if (value >= 0x80) { -- out[rv++] = value | 0x80; -- value >>= 7; -- if (value >= 0x80) { -- out[rv++] = value | 0x80; -- value >>= 7; -- if (value >= 0x80) { -- out[rv++] = value | 0x80; -- value >>= 7; -- } -- } -- } -- } -- /* assert: value<128 */ -- out[rv++] = value; -- return rv; --} -- --/** -- * Pack a signed 32-bit integer and return the number of bytes written. -- * Negative numbers are encoded as two's complement 64-bit integers. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --int32_pack(int32_t value, uint8_t *out) --{ -- if (value < 0) { -- out[0] = value | 0x80; -- out[1] = (value >> 7) | 0x80; -- out[2] = (value >> 14) | 0x80; -- out[3] = (value >> 21) | 0x80; -- out[4] = (value >> 28) | 0x80; -- out[5] = out[6] = out[7] = out[8] = 0xff; -- out[9] = 0x01; -- return 10; -- } else { -- return uint32_pack(value, out); -- } --} -- --/** -- * Pack a signed 32-bit integer using ZigZag encoding and return the number of -- * bytes written. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --sint32_pack(int32_t value, uint8_t *out) --{ -- return uint32_pack(zigzag32(value), out); --} -- --/** -- * Pack a 64-bit unsigned integer using base-128 varint encoding and return the -- * number of bytes written. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static size_t --uint64_pack(uint64_t value, uint8_t *out) --{ -- uint32_t hi = (uint32_t) (value >> 32); -- uint32_t lo = (uint32_t) value; -- unsigned rv; -- -- if (hi == 0) -- return uint32_pack((uint32_t) lo, out); -- out[0] = (lo) | 0x80; -- out[1] = (lo >> 7) | 0x80; -- out[2] = (lo >> 14) | 0x80; -- out[3] = (lo >> 21) | 0x80; -- if (hi < 8) { -- out[4] = (hi << 4) | (lo >> 28); -- return 5; -- } else { -- out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80; -- hi >>= 3; -- } -- rv = 5; -- while (hi >= 128) { -- out[rv++] = hi | 0x80; -- hi >>= 7; -- } -- out[rv++] = hi; -- return rv; --} -- --/** -- * Pack a 64-bit signed integer in ZigZag encoding and return the number of -- * bytes written. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --sint64_pack(int64_t value, uint8_t *out) --{ -- return uint64_pack(zigzag64(value), out); --} -- --/** -- * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire -- * types fixed32, sfixed32, float. Similar to "htole32". -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --fixed32_pack(uint32_t value, void *out) --{ --#if !defined(WORDS_BIGENDIAN) -- memcpy(out, &value, 4); --#else -- uint8_t *buf = out; -- -- buf[0] = value; -- buf[1] = value >> 8; -- buf[2] = value >> 16; -- buf[3] = value >> 24; --#endif -- return 4; --} -- --/** -- * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire -- * types fixed64, sfixed64, double. Similar to "htole64". -- * -- * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit -- * version would be appreciated, plus a way to decide to use 64-bit math where -- * convenient. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --fixed64_pack(uint64_t value, void *out) --{ --#if !defined(WORDS_BIGENDIAN) -- memcpy(out, &value, 8); --#else -- fixed32_pack(value, out); -- fixed32_pack(value >> 32, ((char *) out) + 4); --#endif -- return 8; --} -- --/** -- * Pack a boolean value as an integer and return the number of bytes written. -- * -- * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c -- * that is idiomatic C++ in some STL implementations. -- * -- * \param value -- * Value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --boolean_pack(protobuf_c_boolean value, uint8_t *out) --{ -- *out = value ? TRUE : FALSE; -- return 1; --} -- --/** -- * Pack a NUL-terminated C string and return the number of bytes written. The -- * output includes a length delimiter. -- * -- * The NULL pointer is treated as an empty string. This isn't really necessary, -- * but it allows people to leave required strings blank. (See Issue #13 in the -- * bug tracker for a little more explanation). -- * -- * \param str -- * String to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --string_pack(const char *str, uint8_t *out) --{ -- if (str == NULL) { -- out[0] = 0; -- return 1; -- } else { -- size_t len = strlen(str); -- size_t rv = uint32_pack(len, out); -- memcpy(out + rv, str, len); -- return rv + len; -- } --} -- --/** -- * Pack a ProtobufCBinaryData and return the number of bytes written. The output -- * includes a length delimiter. -- * -- * \param bd -- * ProtobufCBinaryData to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out) --{ -- size_t len = bd->len; -- size_t rv = uint32_pack(len, out); -- memcpy(out + rv, bd->data, len); -- return rv + len; --} -- --/** -- * Pack a ProtobufCMessage and return the number of bytes written. The output -- * includes a length delimiter. -- * -- * \param message -- * ProtobufCMessage object to pack. -- * \param[out] out -- * Packed message. -- * \return -- * Number of bytes written to `out`. -- */ --static inline size_t --prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out) --{ -- if (message == NULL) { -- out[0] = 0; -- return 1; -- } else { -- size_t rv = protobuf_c_message_pack(message, out + 1); -- uint32_t rv_packed_size = uint32_size(rv); -- if (rv_packed_size != 1) -- memmove(out + rv_packed_size, out + 1, rv); -- return uint32_pack(rv, out) + rv; -- } --} -- --/** -- * Pack a field tag. -- * -- * Wire-type will be added in required_field_pack(). -- * -- * \todo Just call uint64_pack on 64-bit platforms. -- * -- * \param id -- * Tag value to encode. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static size_t --tag_pack(uint32_t id, uint8_t *out) --{ -- if (id < (1 << (32 - 3))) -- return uint32_pack(id << 3, out); -- else -- return uint64_pack(((uint64_t) id) << 3, out); --} -- --/** -- * Pack a required field and return the number of bytes written. -- * -- * \param field -- * Field descriptor. -- * \param member -- * The field member. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static size_t --required_field_pack(const ProtobufCFieldDescriptor *field, -- const void *member, uint8_t *out) --{ -- size_t rv = tag_pack(field->id, out); -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SINT32: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + sint32_pack(*(const int32_t *) member, out + rv); -- case PROTOBUF_C_TYPE_INT32: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + int32_pack(*(const uint32_t *) member, out + rv); -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_ENUM: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + uint32_pack(*(const uint32_t *) member, out + rv); -- case PROTOBUF_C_TYPE_SINT64: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + sint64_pack(*(const int64_t *) member, out + rv); -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + uint64_pack(*(const uint64_t *) member, out + rv); -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; -- return rv + fixed32_pack(*(const uint32_t *) member, out + rv); -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; -- return rv + fixed64_pack(*(const uint64_t *) member, out + rv); -- case PROTOBUF_C_TYPE_BOOL: -- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv); -- case PROTOBUF_C_TYPE_STRING: -- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- return rv + string_pack(*(char *const *) member, out + rv); -- case PROTOBUF_C_TYPE_BYTES: -- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv); -- case PROTOBUF_C_TYPE_MESSAGE: -- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv); -- } -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- return 0; --} -- --/** -- * Pack an optional field and return the number of bytes written. -- * -- * \param field -- * Field descriptor. -- * \param has -- * Whether the field is set. -- * \param member -- * The field member. -- * \param[out] out -- * Packed value. -- * \return -- * Number of bytes written to `out`. -- */ --static size_t --optional_field_pack(const ProtobufCFieldDescriptor *field, -- const protobuf_c_boolean *has, -- const void *member, uint8_t *out) --{ -- if (field->type == PROTOBUF_C_TYPE_MESSAGE || -- field->type == PROTOBUF_C_TYPE_STRING) -- { -- const void *ptr = *(const void * const *) member; -- if (ptr == NULL || ptr == field->default_value) -- return 0; -- } else { -- if (!*has) -- return 0; -- } -- return required_field_pack(field, member, out); --} -- --/** -- * Given a field type, return the in-memory size. -- * -- * \todo Implement as a table lookup. -- * -- * \param type -- * Field type. -- * \return -- * Size of the field. -- */ --static inline size_t --sizeof_elt_in_repeated_array(ProtobufCType type) --{ -- switch (type) { -- case PROTOBUF_C_TYPE_SINT32: -- case PROTOBUF_C_TYPE_INT32: -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- case PROTOBUF_C_TYPE_ENUM: -- return 4; -- case PROTOBUF_C_TYPE_SINT64: -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- return 8; -- case PROTOBUF_C_TYPE_BOOL: -- return sizeof(protobuf_c_boolean); -- case PROTOBUF_C_TYPE_STRING: -- case PROTOBUF_C_TYPE_MESSAGE: -- return sizeof(void *); -- case PROTOBUF_C_TYPE_BYTES: -- return sizeof(ProtobufCBinaryData); -- } -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- return 0; --} -- --/** -- * Pack an array of 32-bit quantities. -- * -- * \param[out] out -- * Destination. -- * \param[in] in -- * Source. -- * \param[in] n -- * Number of elements in the source array. -- */ --static void --copy_to_little_endian_32(void *out, const void *in, const unsigned n) --{ --#if !defined(WORDS_BIGENDIAN) -- memcpy(out, in, n * 4); --#else -- unsigned i; -- const uint32_t *ini = in; -- for (i = 0; i < n; i++) -- fixed32_pack(ini[i], (uint32_t *) out + i); --#endif --} -- --/** -- * Pack an array of 64-bit quantities. -- * -- * \param[out] out -- * Destination. -- * \param[in] in -- * Source. -- * \param[in] n -- * Number of elements in the source array. -- */ --static void --copy_to_little_endian_64(void *out, const void *in, const unsigned n) --{ --#if !defined(WORDS_BIGENDIAN) -- memcpy(out, in, n * 8); --#else -- unsigned i; -- const uint64_t *ini = in; -- for (i = 0; i < n; i++) -- fixed64_pack(ini[i], (uint64_t *) out + i); --#endif --} -- --/** -- * Get the minimum number of bytes required to pack a field value of a -- * particular type. -- * -- * \param type -- * Field type. -- * \return -- * Number of bytes. -- */ --static unsigned --get_type_min_size(ProtobufCType type) --{ -- if (type == PROTOBUF_C_TYPE_SFIXED32 || -- type == PROTOBUF_C_TYPE_FIXED32 || -- type == PROTOBUF_C_TYPE_FLOAT) -- { -- return 4; -- } -- if (type == PROTOBUF_C_TYPE_SFIXED64 || -- type == PROTOBUF_C_TYPE_FIXED64 || -- type == PROTOBUF_C_TYPE_DOUBLE) -- { -- return 8; -- } -- return 1; --} -- --/** -- * Packs the elements of a repeated field and returns the serialised field and -- * its length. -- * -- * \param field -- * Field descriptor. -- * \param count -- * Number of elements in the repeated field array. -- * \param member -- * Pointer to the elements for this repeated field. -- * \param[out] out -- * Serialised representation of the repeated field. -- * \return -- * Number of bytes serialised to `out`. -- */ --static size_t --repeated_field_pack(const ProtobufCFieldDescriptor *field, -- size_t count, const void *member, uint8_t *out) --{ -- void *array = *(void * const *) member; -- unsigned i; -- -- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { -- unsigned header_len; -- unsigned len_start; -- unsigned min_length; -- unsigned payload_len; -- unsigned length_size_min; -- unsigned actual_length_size; -- uint8_t *payload_at; -- -- if (count == 0) -- return 0; -- header_len = tag_pack(field->id, out); -- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- len_start = header_len; -- min_length = get_type_min_size(field->type) * count; -- length_size_min = uint32_size(min_length); -- header_len += length_size_min; -- payload_at = out + header_len; -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- copy_to_little_endian_32(payload_at, array, count); -- payload_at += count * 4; -- break; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- copy_to_little_endian_64(payload_at, array, count); -- payload_at += count * 8; -- break; -- case PROTOBUF_C_TYPE_INT32: { -- const int32_t *arr = (const int32_t *) array; -- for (i = 0; i < count; i++) -- payload_at += int32_pack(arr[i], payload_at); -- break; -- } -- case PROTOBUF_C_TYPE_SINT32: { -- const int32_t *arr = (const int32_t *) array; -- for (i = 0; i < count; i++) -- payload_at += sint32_pack(arr[i], payload_at); -- break; -- } -- case PROTOBUF_C_TYPE_SINT64: { -- const int64_t *arr = (const int64_t *) array; -- for (i = 0; i < count; i++) -- payload_at += sint64_pack(arr[i], payload_at); -- break; -- } -- case PROTOBUF_C_TYPE_ENUM: -- case PROTOBUF_C_TYPE_UINT32: { -- const uint32_t *arr = (const uint32_t *) array; -- for (i = 0; i < count; i++) -- payload_at += uint32_pack(arr[i], payload_at); -- break; -- } -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: { -- const uint64_t *arr = (const uint64_t *) array; -- for (i = 0; i < count; i++) -- payload_at += uint64_pack(arr[i], payload_at); -- break; -- } -- case PROTOBUF_C_TYPE_BOOL: { -- const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array; -- for (i = 0; i < count; i++) -- payload_at += boolean_pack(arr[i], payload_at); -- break; -- } -- default: -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- } -- -- payload_len = payload_at - (out + header_len); -- actual_length_size = uint32_size(payload_len); -- if (length_size_min != actual_length_size) { -- assert(actual_length_size == length_size_min + 1); -- memmove(out + header_len + 1, out + header_len, -- payload_len); -- header_len++; -- } -- uint32_pack(payload_len, out + len_start); -- return header_len + payload_len; -- } else { -- /* not "packed" cased */ -- /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ -- size_t rv = 0; -- unsigned siz = sizeof_elt_in_repeated_array(field->type); -- -- for (i = 0; i < count; i++) { -- rv += required_field_pack(field, array, out + rv); -- array = (char *)array + siz; -- } -- return rv; -- } --} -- --static size_t --unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out) --{ -- size_t rv = tag_pack(field->tag, out); -- out[0] |= field->wire_type; -- memcpy(out + rv, field->data, field->len); -- return rv + field->len; --} -- --/**@}*/ -- --size_t --protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) --{ -- unsigned i; -- size_t rv = 0; -- -- ASSERT_IS_MESSAGE(message); -- for (i = 0; i < message->descriptor->n_fields; i++) { -- const ProtobufCFieldDescriptor *field = -- message->descriptor->fields + i; -- const void *member = ((const char *) message) + field->offset; -- -- /* -- * It doesn't hurt to compute qmember (a pointer to the -- * quantifier field of the structure), but the pointer is only -- * valid if the field is: -- * - a repeated field, or -- * - an optional field that isn't a pointer type -- * (Meaning: not a message or a string). -- */ -- const void *qmember = -- ((const char *) message) + field->quantifier_offset; -- -- if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -- rv += required_field_pack(field, member, out + rv); -- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -- /* -- * Note that qmember is bogus for strings and messages, -- * but it isn't used. -- */ -- rv += optional_field_pack(field, qmember, member, out + rv); -- } else { -- rv += repeated_field_pack(field, *(const size_t *) qmember, -- member, out + rv); -- } -- } -- for (i = 0; i < message->n_unknown_fields; i++) -- rv += unknown_field_pack(&message->unknown_fields[i], out + rv); -- return rv; --} -- --/** -- * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation -- * -- * Routines mainly used by protobuf_c_message_pack_to_buffer(). -- * -- * \ingroup internal -- * @{ -- */ -- --/** -- * Pack a required field to a virtual buffer. -- * -- * \param field -- * Field descriptor. -- * \param member -- * The element to be packed. -- * \param[out] buffer -- * Virtual buffer to append data to. -- * \return -- * Number of bytes packed. -- */ --static size_t --required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -- const void *member, ProtobufCBuffer *buffer) --{ -- size_t rv; -- uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; -- -- rv = tag_pack(field->id, scratch); -- switch (field->type) { -- case PROTOBUF_C_TYPE_SINT32: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += sint32_pack(*(const int32_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_INT32: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += int32_pack(*(const uint32_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_ENUM: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += uint32_pack(*(const uint32_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_SINT64: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += sint64_pack(*(const int64_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += uint64_pack(*(const uint64_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; -- rv += fixed32_pack(*(const uint32_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; -- rv += fixed64_pack(*(const uint64_t *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_BOOL: -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -- rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv); -- buffer->append(buffer, rv, scratch); -- break; -- case PROTOBUF_C_TYPE_STRING: { -- const char *str = *(char *const *) member; -- size_t sublen = str ? strlen(str) : 0; -- -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- rv += uint32_pack(sublen, scratch + rv); -- buffer->append(buffer, rv, scratch); -- buffer->append(buffer, sublen, (const uint8_t *) str); -- rv += sublen; -- break; -- } -- case PROTOBUF_C_TYPE_BYTES: { -- const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member); -- size_t sublen = bd->len; -- -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- rv += uint32_pack(sublen, scratch + rv); -- buffer->append(buffer, rv, scratch); -- buffer->append(buffer, sublen, bd->data); -- rv += sublen; -- break; -- } -- case PROTOBUF_C_TYPE_MESSAGE: { -- uint8_t simple_buffer_scratch[256]; -- size_t sublen; -- const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; -- ProtobufCBufferSimple simple_buffer = -- PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch); -- -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- if (msg == NULL) -- sublen = 0; -- else -- sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base); -- rv += uint32_pack(sublen, scratch + rv); -- buffer->append(buffer, rv, scratch); -- buffer->append(buffer, sublen, simple_buffer.data); -- rv += sublen; -- PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer); -- break; -- } -- default: -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- } -- return rv; --} -- --/** -- * Pack an optional field to a buffer. -- * -- * \param field -- * Field descriptor. -- * \param has -- * Whether the field is set. -- * \param member -- * The element to be packed. -- * \param[out] buffer -- * Virtual buffer to append data to. -- * \return -- * Number of bytes serialised to `buffer`. -- */ --static size_t --optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -- const protobuf_c_boolean *has, -- const void *member, ProtobufCBuffer *buffer) --{ -- if (field->type == PROTOBUF_C_TYPE_MESSAGE || -- field->type == PROTOBUF_C_TYPE_STRING) -- { -- const void *ptr = *(const void *const *) member; -- if (ptr == NULL || ptr == field->default_value) -- return 0; -- } else { -- if (!*has) -- return 0; -- } -- return required_field_pack_to_buffer(field, member, buffer); --} -- --/** -- * Get the packed size of an array of same field type. -- * -- * \param field -- * Field descriptor. -- * \param count -- * Number of elements of this type. -- * \param array -- * The elements to get the size of. -- * \return -- * Number of bytes required. -- */ --static size_t --get_packed_payload_length(const ProtobufCFieldDescriptor *field, -- unsigned count, const void *array) --{ -- unsigned rv = 0; -- unsigned i; -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- return count * 4; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- return count * 8; -- case PROTOBUF_C_TYPE_INT32: { -- const int32_t *arr = (const int32_t *) array; -- for (i = 0; i < count; i++) -- rv += int32_size(arr[i]); -- break; -- } -- case PROTOBUF_C_TYPE_SINT32: { -- const int32_t *arr = (const int32_t *) array; -- for (i = 0; i < count; i++) -- rv += sint32_size(arr[i]); -- break; -- } -- case PROTOBUF_C_TYPE_ENUM: -- case PROTOBUF_C_TYPE_UINT32: { -- const uint32_t *arr = (const uint32_t *) array; -- for (i = 0; i < count; i++) -- rv += uint32_size(arr[i]); -- break; -- } -- case PROTOBUF_C_TYPE_SINT64: { -- const int64_t *arr = (const int64_t *) array; -- for (i = 0; i < count; i++) -- rv += sint64_size(arr[i]); -- break; -- } -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: { -- const uint64_t *arr = (const uint64_t *) array; -- for (i = 0; i < count; i++) -- rv += uint64_size(arr[i]); -- break; -- } -- case PROTOBUF_C_TYPE_BOOL: -- return count; -- default: -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- } -- return rv; --} -- --/** -- * Pack an array of same field type to a virtual buffer. -- * -- * \param field -- * Field descriptor. -- * \param count -- * Number of elements of this type. -- * \param array -- * The elements to get the size of. -- * \param[out] buffer -- * Virtual buffer to append data to. -- * \return -- * Number of bytes packed. -- */ --static size_t --pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, -- unsigned count, const void *array, -- ProtobufCBuffer *buffer) --{ -- uint8_t scratch[16]; -- size_t rv = 0; -- unsigned i; -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: --#if !defined(WORDS_BIGENDIAN) -- rv = count * 4; -- goto no_packing_needed; --#else -- for (i = 0; i < count; i++) { -- unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; --#endif -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: --#if !defined(WORDS_BIGENDIAN) -- rv = count * 8; -- goto no_packing_needed; --#else -- for (i = 0; i < count; i++) { -- unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; --#endif -- case PROTOBUF_C_TYPE_INT32: -- for (i = 0; i < count; i++) { -- unsigned len = int32_pack(((int32_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; -- case PROTOBUF_C_TYPE_SINT32: -- for (i = 0; i < count; i++) { -- unsigned len = sint32_pack(((int32_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; -- case PROTOBUF_C_TYPE_ENUM: -- case PROTOBUF_C_TYPE_UINT32: -- for (i = 0; i < count; i++) { -- unsigned len = uint32_pack(((uint32_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; -- case PROTOBUF_C_TYPE_SINT64: -- for (i = 0; i < count; i++) { -- unsigned len = sint64_pack(((int64_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- for (i = 0; i < count; i++) { -- unsigned len = uint64_pack(((uint64_t *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- break; -- case PROTOBUF_C_TYPE_BOOL: -- for (i = 0; i < count; i++) { -- unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch); -- buffer->append(buffer, len, scratch); -- rv += len; -- } -- return count; -- default: -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- } -- return rv; -- --no_packing_needed: -- buffer->append(buffer, rv, array); -- return rv; --} -- --static size_t --repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -- unsigned count, const void *member, -- ProtobufCBuffer *buffer) --{ -- char *array = *(char * const *) member; -- -- if (count == 0) -- return 0; -- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { -- uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; -- size_t rv = tag_pack(field->id, scratch); -- size_t payload_len = get_packed_payload_length(field, count, array); -- size_t tmp; -- -- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -- rv += uint32_pack(payload_len, scratch + rv); -- buffer->append(buffer, rv, scratch); -- tmp = pack_buffer_packed_payload(field, count, array, buffer); -- assert(tmp == payload_len); -- return rv + payload_len; -- } else { -- size_t siz; -- unsigned i; -- /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ -- unsigned rv = 0; -- -- siz = sizeof_elt_in_repeated_array(field->type); -- for (i = 0; i < count; i++) { -- rv += required_field_pack_to_buffer(field, array, buffer); -- array += siz; -- } -- return rv; -- } --} -- --static size_t --unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field, -- ProtobufCBuffer *buffer) --{ -- uint8_t header[MAX_UINT64_ENCODED_SIZE]; -- size_t rv = tag_pack(field->tag, header); -- -- header[0] |= field->wire_type; -- buffer->append(buffer, rv, header); -- buffer->append(buffer, field->len, field->data); -- return rv + field->len; --} -- --/**@}*/ -- --size_t --protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message, -- ProtobufCBuffer *buffer) --{ -- unsigned i; -- size_t rv = 0; -- -- ASSERT_IS_MESSAGE(message); -- for (i = 0; i < message->descriptor->n_fields; i++) { -- const ProtobufCFieldDescriptor *field = -- message->descriptor->fields + i; -- const void *member = -- ((const char *) message) + field->offset; -- const void *qmember = -- ((const char *) message) + field->quantifier_offset; -- -- if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -- rv += required_field_pack_to_buffer(field, member, buffer); -- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -- rv += optional_field_pack_to_buffer( -- field, -- qmember, -- member, -- buffer -- ); -- } else { -- rv += repeated_field_pack_to_buffer( -- field, -- *(const size_t *) qmember, -- member, -- buffer -- ); -- } -- } -- for (i = 0; i < message->n_unknown_fields; i++) -- rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); -- -- return rv; --} -- --/** -- * \defgroup unpack unpacking implementation -- * -- * Routines mainly used by the unpacking functions. -- * -- * \ingroup internal -- * @{ -- */ -- --static inline int --int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value) --{ -- unsigned n; -- unsigned start; -- -- if (n_ranges == 0) -- return -1; -- start = 0; -- n = n_ranges; -- while (n > 1) { -- unsigned mid = start + n / 2; -- -- if (value < ranges[mid].start_value) { -- n = mid - start; -- } else if (value >= ranges[mid].start_value + -- (int) (ranges[mid + 1].orig_index - -- ranges[mid].orig_index)) -- { -- unsigned new_start = mid + 1; -- n = start + n - new_start; -- start = new_start; -- } else -- return (value - ranges[mid].start_value) + -- ranges[mid].orig_index; -- } -- if (n > 0) { -- unsigned start_orig_index = ranges[start].orig_index; -- unsigned range_size = -- ranges[start + 1].orig_index - start_orig_index; -- -- if (ranges[start].start_value <= value && -- value < (int) (ranges[start].start_value + range_size)) -- { -- return (value - ranges[start].start_value) + -- start_orig_index; -- } -- } -- return -1; --} -- --static size_t --parse_tag_and_wiretype(size_t len, -- const uint8_t *data, -- uint32_t *tag_out, -- ProtobufCWireType *wiretype_out) --{ -- unsigned max_rv = len > 5 ? 5 : len; -- uint32_t tag = (data[0] & 0x7f) >> 3; -- unsigned shift = 4; -- unsigned rv; -- -- *wiretype_out = data[0] & 7; -- if ((data[0] & 0x80) == 0) { -- *tag_out = tag; -- return 1; -- } -- for (rv = 1; rv < max_rv; rv++) { -- if (data[rv] & 0x80) { -- tag |= (data[rv] & 0x7f) << shift; -- shift += 7; -- } else { -- tag |= data[rv] << shift; -- *tag_out = tag; -- return rv + 1; -- } -- } -- return 0; /* error: bad header */ --} -- --/* sizeof(ScannedMember) must be <= (1< len) { -- PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val); -- return 0; -- } -- return hdr_len + val; --} -- --static size_t --max_b128_numbers(size_t len, const uint8_t *data) --{ -- size_t rv = 0; -- while (len--) -- if ((*data++ & 0x80) == 0) -- ++rv; -- return rv; --} -- --/**@}*/ -- --/** -- * Merge earlier message into a latter message. -- * -- * For numeric types and strings, if the same value appears multiple -- * times, the parser accepts the last value it sees. For embedded -- * message fields, the parser merges multiple instances of the same -- * field. That is, all singular scalar fields in the latter instance -- * replace those in the former, singular embedded messages are merged, -- * and repeated fields are concatenated. -- * -- * The earlier message should be freed after calling this function, as -- * some of its fields may have been reused and changed to their default -- * values during the merge. -- */ --static protobuf_c_boolean --merge_messages(ProtobufCMessage *earlier_msg, -- ProtobufCMessage *latter_msg, -- ProtobufCAllocator *allocator) --{ -- unsigned i; -- const ProtobufCFieldDescriptor *fields = -- earlier_msg->descriptor->fields; -- for (i = 0; i < latter_msg->descriptor->n_fields; i++) { -- if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { -- size_t *n_earlier = -- STRUCT_MEMBER_PTR(size_t, earlier_msg, -- fields[i].quantifier_offset); -- uint8_t **p_earlier = -- STRUCT_MEMBER_PTR(uint8_t *, earlier_msg, -- fields[i].offset); -- size_t *n_latter = -- STRUCT_MEMBER_PTR(size_t, latter_msg, -- fields[i].quantifier_offset); -- uint8_t **p_latter = -- STRUCT_MEMBER_PTR(uint8_t *, latter_msg, -- fields[i].offset); -- -- if (*n_earlier > 0) { -- if (*n_latter > 0) { -- /* Concatenate the repeated field */ -- size_t el_size = -- sizeof_elt_in_repeated_array(fields[i].type); -- uint8_t *new_field; -- -- new_field = do_alloc(allocator, -- (*n_earlier + *n_latter) * el_size); -- if (!new_field) -- return FALSE; -- -- memcpy(new_field, *p_earlier, -- *n_earlier * el_size); -- memcpy(new_field + -- *n_earlier * el_size, -- *p_latter, -- *n_latter * el_size); -- -- do_free(allocator, *p_latter); -- do_free(allocator, *p_earlier); -- *p_latter = new_field; -- *n_latter = *n_earlier + *n_latter; -- } else { -- /* Zero copy the repeated field from the earlier message */ -- *n_latter = *n_earlier; -- *p_latter = *p_earlier; -- } -- /* Make sure the field does not get double freed */ -- *n_earlier = 0; -- *p_earlier = 0; -- } -- } else if (fields[i].type == PROTOBUF_C_TYPE_MESSAGE) { -- ProtobufCMessage **em = -- STRUCT_MEMBER_PTR(ProtobufCMessage *, -- earlier_msg, -- fields[i].offset); -- ProtobufCMessage **lm = -- STRUCT_MEMBER_PTR(ProtobufCMessage *, -- latter_msg, -- fields[i].offset); -- if (*em != NULL) { -- if (*lm != NULL) { -- if (!merge_messages -- (*em, *lm, allocator)) -- return FALSE; -- } else { -- /* Zero copy the optional message */ -- assert(fields[i].label == -- PROTOBUF_C_LABEL_OPTIONAL); -- *lm = *em; -- *em = NULL; -- } -- } -- } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) { -- size_t el_size = 0; -- protobuf_c_boolean need_to_merge = FALSE; -- void *earlier_elem = -- STRUCT_MEMBER_P(earlier_msg, fields[i].offset); -- void *latter_elem = -- STRUCT_MEMBER_P(latter_msg, fields[i].offset); -- const void *def_val = fields[i].default_value; -- -- switch (fields[i].type) { -- case PROTOBUF_C_TYPE_BYTES: { -- el_size = sizeof(ProtobufCBinaryData); -- uint8_t *e_data = -- ((ProtobufCBinaryData *) earlier_elem)->data; -- uint8_t *l_data = -- ((ProtobufCBinaryData *) latter_elem)->data; -- const ProtobufCBinaryData *d_bd = -- (ProtobufCBinaryData *) def_val; -- -- need_to_merge = -- (e_data != NULL && -- (d_bd != NULL && -- e_data != d_bd->data)) && -- (l_data == NULL || -- (d_bd != NULL && -- l_data == d_bd->data)); -- break; -- } -- case PROTOBUF_C_TYPE_STRING: { -- el_size = sizeof(char *); -- char *e_str = *(char **) earlier_elem; -- char *l_str = *(char **) latter_elem; -- const char *d_str = def_val; -- -- need_to_merge = e_str != d_str && l_str == d_str; -- break; -- } -- default: { -- el_size = sizeof_elt_in_repeated_array(fields[i].type); -- -- need_to_merge = -- STRUCT_MEMBER(protobuf_c_boolean, -- earlier_msg, -- fields[i].quantifier_offset) && -- !STRUCT_MEMBER(protobuf_c_boolean, -- latter_msg, -- fields[i].quantifier_offset); -- break; -- } -- } -- -- if (need_to_merge) { -- memcpy(latter_elem, earlier_elem, el_size); -- /* -- * Reset the element from the old message to 0 -- * to make sure earlier message deallocation -- * doesn't corrupt zero-copied data in the new -- * message, earlier message will be freed after -- * this function is called anyway -- */ -- memset(earlier_elem, 0, el_size); -- -- if (fields[i].quantifier_offset != 0) { -- /* Set the has field, if applicable */ -- STRUCT_MEMBER(protobuf_c_boolean, -- latter_msg, -- fields[i]. -- quantifier_offset) = TRUE; -- STRUCT_MEMBER(protobuf_c_boolean, -- earlier_msg, -- fields[i]. -- quantifier_offset) = FALSE; -- } -- } -- } -- } -- return TRUE; --} -- --/** -- * Count packed elements. -- * -- * Given a raw slab of packed-repeated values, determine the number of -- * elements. This function detects certain kinds of errors but not -- * others; the remaining error checking is done by -- * parse_packed_repeated_member(). -- */ --static protobuf_c_boolean --count_packed_elements(ProtobufCType type, -- size_t len, const uint8_t *data, size_t *count_out) --{ -- switch (type) { -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- if (len % 4 != 0) { -- PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types"); -- return FALSE; -- } -- *count_out = len / 4; -- return TRUE; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- if (len % 8 != 0) { -- PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types"); -- return FALSE; -- } -- *count_out = len / 8; -- return TRUE; -- case PROTOBUF_C_TYPE_INT32: -- case PROTOBUF_C_TYPE_SINT32: -- case PROTOBUF_C_TYPE_ENUM: -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_SINT64: -- case PROTOBUF_C_TYPE_UINT64: -- *count_out = max_b128_numbers(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_BOOL: -- *count_out = len; -- return TRUE; -- case PROTOBUF_C_TYPE_STRING: -- case PROTOBUF_C_TYPE_BYTES: -- case PROTOBUF_C_TYPE_MESSAGE: -- default: -- PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type); -- return FALSE; -- } --} -- --static inline uint32_t --parse_uint32(unsigned len, const uint8_t *data) --{ -- uint32_t rv = data[0] & 0x7f; -- if (len > 1) { -- rv |= ((uint32_t) (data[1] & 0x7f) << 7); -- if (len > 2) { -- rv |= ((uint32_t) (data[2] & 0x7f) << 14); -- if (len > 3) { -- rv |= ((uint32_t) (data[3] & 0x7f) << 21); -- if (len > 4) -- rv |= ((uint32_t) (data[4]) << 28); -- } -- } -- } -- return rv; --} -- --static inline uint32_t --parse_int32(unsigned len, const uint8_t *data) --{ -- return parse_uint32(len, data); --} -- --static inline int32_t --unzigzag32(uint32_t v) --{ -- if (v & 1) -- return -(v >> 1) - 1; -- else -- return v >> 1; --} -- --static inline uint32_t --parse_fixed_uint32(const uint8_t *data) --{ --#if !defined(WORDS_BIGENDIAN) -- uint32_t t; -- memcpy(&t, data, 4); -- return t; --#else -- return data[0] | -- ((uint32_t) (data[1]) << 8) | -- ((uint32_t) (data[2]) << 16) | -- ((uint32_t) (data[3]) << 24); --#endif --} -- --static uint64_t --parse_uint64(unsigned len, const uint8_t *data) --{ -- unsigned shift, i; -- uint64_t rv; -- -- if (len < 5) -- return parse_uint32(len, data); -- rv = ((uint64_t) (data[0] & 0x7f)) | -- ((uint64_t) (data[1] & 0x7f) << 7) | -- ((uint64_t) (data[2] & 0x7f) << 14) | -- ((uint64_t) (data[3] & 0x7f) << 21); -- shift = 28; -- for (i = 4; i < len; i++) { -- rv |= (((uint64_t) (data[i] & 0x7f)) << shift); -- shift += 7; -- } -- return rv; --} -- --static inline int64_t --unzigzag64(uint64_t v) --{ -- if (v & 1) -- return -(v >> 1) - 1; -- else -- return v >> 1; --} -- --static inline uint64_t --parse_fixed_uint64(const uint8_t *data) --{ --#if !defined(WORDS_BIGENDIAN) -- uint64_t t; -- memcpy(&t, data, 8); -- return t; --#else -- return (uint64_t) parse_fixed_uint32(data) | -- (((uint64_t) parse_fixed_uint32(data + 4)) << 32); --#endif --} -- --static protobuf_c_boolean --parse_boolean(unsigned len, const uint8_t *data) --{ -- unsigned i; -- for (i = 0; i < len; i++) -- if (data[i] & 0x7f) -- return TRUE; -- return FALSE; --} -- --static protobuf_c_boolean --parse_required_member(ScannedMember *scanned_member, -- void *member, -- ProtobufCAllocator *allocator, -- protobuf_c_boolean maybe_clear) --{ -- unsigned len = scanned_member->len; -- const uint8_t *data = scanned_member->data; -- ProtobufCWireType wire_type = scanned_member->wire_type; -- -- switch (scanned_member->field->type) { -- case PROTOBUF_C_TYPE_INT32: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(uint32_t *) member = parse_int32(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_UINT32: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(uint32_t *) member = parse_uint32(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_SINT32: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(int32_t *) member = unzigzag32(parse_uint32(len, data)); -- return TRUE; -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT) -- return FALSE; -- *(uint32_t *) member = parse_fixed_uint32(data); -- return TRUE; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(uint64_t *) member = parse_uint64(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_SINT64: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(int64_t *) member = unzigzag64(parse_uint64(len, data)); -- return TRUE; -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT) -- return FALSE; -- *(uint64_t *) member = parse_fixed_uint64(data); -- return TRUE; -- case PROTOBUF_C_TYPE_BOOL: -- *(protobuf_c_boolean *) member = parse_boolean(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_ENUM: -- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -- return FALSE; -- *(uint32_t *) member = parse_uint32(len, data); -- return TRUE; -- case PROTOBUF_C_TYPE_STRING: { -- char **pstr = member; -- unsigned pref_len = scanned_member->length_prefix_len; -- -- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -- return FALSE; -- -- if (maybe_clear && *pstr != NULL) { -- const char *def = scanned_member->field->default_value; -- if (*pstr != NULL && *pstr != def) -- do_free(allocator, *pstr); -- } -- *pstr = do_alloc(allocator, len - pref_len + 1); -- if (*pstr == NULL) -- return FALSE; -- memcpy(*pstr, data + pref_len, len - pref_len); -- (*pstr)[len - pref_len] = 0; -- return TRUE; -- } -- case PROTOBUF_C_TYPE_BYTES: { -- ProtobufCBinaryData *bd = member; -- const ProtobufCBinaryData *def_bd; -- unsigned pref_len = scanned_member->length_prefix_len; -- -- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -- return FALSE; -- -- def_bd = scanned_member->field->default_value; -- if (maybe_clear && -- bd->data != NULL && -- (def_bd == NULL || bd->data != def_bd->data)) -- { -- do_free(allocator, bd->data); -- } -- if (len - pref_len > 0) { -- bd->data = do_alloc(allocator, len - pref_len); -- if (bd->data == NULL) -- return FALSE; -- memcpy(bd->data, data + pref_len, len - pref_len); -- } -- bd->len = len - pref_len; -- return TRUE; -- } -- case PROTOBUF_C_TYPE_MESSAGE: { -- ProtobufCMessage **pmessage = member; -- ProtobufCMessage *subm; -- const ProtobufCMessage *def_mess; -- protobuf_c_boolean merge_successful = TRUE; -- unsigned pref_len = scanned_member->length_prefix_len; -- -- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -- return FALSE; -- -- def_mess = scanned_member->field->default_value; -- subm = protobuf_c_message_unpack(scanned_member->field->descriptor, -- allocator, -- len - pref_len, -- data + pref_len); -- -- if (maybe_clear && -- *pmessage != NULL && -- *pmessage != def_mess) -- { -- if (subm != NULL) -- merge_successful = merge_messages(*pmessage, subm, allocator); -- /* Delete the previous message */ -- protobuf_c_message_free_unpacked(*pmessage, allocator); -- } -- *pmessage = subm; -- if (subm == NULL || !merge_successful) -- return FALSE; -- return TRUE; -- } -- } -- return FALSE; --} -- --static protobuf_c_boolean --parse_optional_member(ScannedMember *scanned_member, -- void *member, -- ProtobufCMessage *message, -- ProtobufCAllocator *allocator) --{ -- if (!parse_required_member(scanned_member, member, allocator, TRUE)) -- return FALSE; -- if (scanned_member->field->quantifier_offset != 0) -- STRUCT_MEMBER(protobuf_c_boolean, -- message, -- scanned_member->field->quantifier_offset) = TRUE; -- return TRUE; --} -- --static protobuf_c_boolean --parse_repeated_member(ScannedMember *scanned_member, -- void *member, -- ProtobufCMessage *message, -- ProtobufCAllocator *allocator) --{ -- const ProtobufCFieldDescriptor *field = scanned_member->field; -- size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); -- size_t siz = sizeof_elt_in_repeated_array(field->type); -- char *array = *(char **) member; -- -- if (!parse_required_member(scanned_member, array + siz * (*p_n), -- allocator, FALSE)) -- { -- return FALSE; -- } -- *p_n += 1; -- return TRUE; --} -- --static unsigned --scan_varint(unsigned len, const uint8_t *data) --{ -- unsigned i; -- if (len > 10) -- len = 10; -- for (i = 0; i < len; i++) -- if ((data[i] & 0x80) == 0) -- break; -- if (i == len) -- return 0; -- return i + 1; --} -- --static protobuf_c_boolean --parse_packed_repeated_member(ScannedMember *scanned_member, -- void *member, -- ProtobufCMessage *message) --{ -- const ProtobufCFieldDescriptor *field = scanned_member->field; -- size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); -- size_t siz = sizeof_elt_in_repeated_array(field->type); -- void *array = *(void **) member + siz * (*p_n); -- const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len; -- size_t rem = scanned_member->len - scanned_member->length_prefix_len; -- size_t count = 0; -- unsigned i; -- -- switch (field->type) { -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- count = (scanned_member->len - scanned_member->length_prefix_len) / 4; --#if !defined(WORDS_BIGENDIAN) -- goto no_unpacking_needed; --#else -- for (i = 0; i < count; i++) { -- ((uint32_t *) array)[i] = parse_fixed_uint32(at); -- at += 4; -- } -- break; --#endif -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- count = (scanned_member->len - scanned_member->length_prefix_len) / 8; --#if !defined(WORDS_BIGENDIAN) -- goto no_unpacking_needed; --#else -- for (i = 0; i < count; i++) { -- ((uint64_t *) array)[i] = parse_fixed_uint64(at); -- at += 8; -- } -- break; --#endif -- case PROTOBUF_C_TYPE_INT32: -- while (rem > 0) { -- unsigned s = scan_varint(rem, at); -- if (s == 0) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value"); -- return FALSE; -- } -- ((int32_t *) array)[count++] = parse_int32(s, at); -- at += s; -- rem -= s; -- } -- break; -- case PROTOBUF_C_TYPE_SINT32: -- while (rem > 0) { -- unsigned s = scan_varint(rem, at); -- if (s == 0) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value"); -- return FALSE; -- } -- ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at)); -- at += s; -- rem -= s; -- } -- break; -- case PROTOBUF_C_TYPE_ENUM: -- case PROTOBUF_C_TYPE_UINT32: -- while (rem > 0) { -- unsigned s = scan_varint(rem, at); -- if (s == 0) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value"); -- return FALSE; -- } -- ((uint32_t *) array)[count++] = parse_uint32(s, at); -- at += s; -- rem -= s; -- } -- break; -- -- case PROTOBUF_C_TYPE_SINT64: -- while (rem > 0) { -- unsigned s = scan_varint(rem, at); -- if (s == 0) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value"); -- return FALSE; -- } -- ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at)); -- at += s; -- rem -= s; -- } -- break; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_UINT64: -- while (rem > 0) { -- unsigned s = scan_varint(rem, at); -- if (s == 0) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value"); -- return FALSE; -- } -- ((int64_t *) array)[count++] = parse_uint64(s, at); -- at += s; -- rem -= s; -- } -- break; -- case PROTOBUF_C_TYPE_BOOL: -- count = rem; -- for (i = 0; i < count; i++) { -- if (at[i] > 1) { -- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value"); -- return FALSE; -- } -- ((protobuf_c_boolean *) array)[i] = at[i]; -- } -- break; -- default: -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- } -- *p_n += count; -- return TRUE; -- --#if !defined(WORDS_BIGENDIAN) --no_unpacking_needed: -- memcpy(array, at, count * siz); -- *p_n += count; -- return TRUE; --#endif --} -- --static protobuf_c_boolean --is_packable_type(ProtobufCType type) --{ -- return -- type != PROTOBUF_C_TYPE_STRING && -- type != PROTOBUF_C_TYPE_BYTES && -- type != PROTOBUF_C_TYPE_MESSAGE; --} -- --static protobuf_c_boolean --parse_member(ScannedMember *scanned_member, -- ProtobufCMessage *message, -- ProtobufCAllocator *allocator) --{ -- const ProtobufCFieldDescriptor *field = scanned_member->field; -- void *member; -- -- if (field == NULL) { -- ProtobufCMessageUnknownField *ufield = -- message->unknown_fields + -- (message->n_unknown_fields++); -- ufield->tag = scanned_member->tag; -- ufield->wire_type = scanned_member->wire_type; -- ufield->len = scanned_member->len; -- ufield->data = do_alloc(allocator, scanned_member->len); -- if (ufield->data == NULL) -- return FALSE; -- memcpy(ufield->data, scanned_member->data, ufield->len); -- return TRUE; -- } -- member = (char *) message + field->offset; -- switch (field->label) { -- case PROTOBUF_C_LABEL_REQUIRED: -- return parse_required_member(scanned_member, member, -- allocator, TRUE); -- case PROTOBUF_C_LABEL_OPTIONAL: -- return parse_optional_member(scanned_member, member, -- message, allocator); -- case PROTOBUF_C_LABEL_REPEATED: -- if (scanned_member->wire_type == -- PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && -- (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || -- is_packable_type(field->type))) -- { -- return parse_packed_repeated_member(scanned_member, -- member, message); -- } else { -- return parse_repeated_member(scanned_member, -- member, message, -- allocator); -- } -- } -- PROTOBUF_C__ASSERT_NOT_REACHED(); -- return 0; --} -- --/** -- * Initialise messages generated by old code. -- * -- * This function is used if desc->message_init == NULL (which occurs -- * for old code, and which would be useful to support allocating -- * descriptors dynamically). -- */ --static void --message_init_generic(const ProtobufCMessageDescriptor *desc, -- ProtobufCMessage *message) --{ -- unsigned i; -- -- memset(message, 0, desc->sizeof_message); -- message->descriptor = desc; -- for (i = 0; i < desc->n_fields; i++) { -- if (desc->fields[i].default_value != NULL && -- desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED) -- { -- void *field = -- STRUCT_MEMBER_P(message, desc->fields[i].offset); -- const void *dv = desc->fields[i].default_value; -- -- switch (desc->fields[i].type) { -- case PROTOBUF_C_TYPE_INT32: -- case PROTOBUF_C_TYPE_SINT32: -- case PROTOBUF_C_TYPE_SFIXED32: -- case PROTOBUF_C_TYPE_UINT32: -- case PROTOBUF_C_TYPE_FIXED32: -- case PROTOBUF_C_TYPE_FLOAT: -- case PROTOBUF_C_TYPE_ENUM: -- memcpy(field, dv, 4); -- break; -- case PROTOBUF_C_TYPE_INT64: -- case PROTOBUF_C_TYPE_SINT64: -- case PROTOBUF_C_TYPE_SFIXED64: -- case PROTOBUF_C_TYPE_UINT64: -- case PROTOBUF_C_TYPE_FIXED64: -- case PROTOBUF_C_TYPE_DOUBLE: -- memcpy(field, dv, 8); -- break; -- case PROTOBUF_C_TYPE_BOOL: -- memcpy(field, dv, sizeof(protobuf_c_boolean)); -- break; -- case PROTOBUF_C_TYPE_BYTES: -- memcpy(field, dv, sizeof(ProtobufCBinaryData)); -- break; -- -- case PROTOBUF_C_TYPE_STRING: -- case PROTOBUF_C_TYPE_MESSAGE: -- /* -- * The next line essentially implements a cast -- * from const, which is totally unavoidable. -- */ -- *(const void **) field = dv; -- break; -- } -- } -- } --} -- --/**@}*/ -- --/* -- * ScannedMember slabs (an unpacking implementation detail). Before doing real -- * unpacking, we first scan through the elements to see how many there are (for -- * repeated fields), and which field to use (for non-repeated fields given -- * twice). -- * -- * In order to avoid allocations for small messages, we keep a stack-allocated -- * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we -- * fill that up, we allocate each slab twice as large as the previous one. -- */ --#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4 -- --/* -- * The number of slabs, including the stack-allocated ones; choose the number so -- * that we would overflow if we needed a slab larger than provided. -- */ --#define MAX_SCANNED_MEMBER_SLAB \ -- (sizeof(unsigned int)*8 - 1 \ -- - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \ -- - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2) -- --#define REQUIRED_FIELD_BITMAP_SET(index) \ -- (required_fields_bitmap[(index)/8] |= (1<<((index)%8))) -- --#define REQUIRED_FIELD_BITMAP_IS_SET(index) \ -- (required_fields_bitmap[(index)/8] & (1<<((index)%8))) -- --ProtobufCMessage * --protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc, -- ProtobufCAllocator *allocator, -- size_t len, const uint8_t *data) --{ -- ProtobufCMessage *rv; -- size_t rem = len; -- const uint8_t *at = data; -- const ProtobufCFieldDescriptor *last_field = desc->fields + 0; -- ScannedMember first_member_slab[1 << -- FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2]; -- -- /* -- * scanned_member_slabs[i] is an array of arrays of ScannedMember. -- * The first slab (scanned_member_slabs[0] is just a pointer to -- * first_member_slab), above. All subsequent slabs will be allocated -- * using the allocator. -- */ -- ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1]; -- unsigned which_slab = 0; /* the slab we are currently populating */ -- unsigned in_slab_index = 0; /* number of members in the slab */ -- size_t n_unknown = 0; -- unsigned f; -- unsigned j; -- unsigned i_slab; -- unsigned last_field_index = 0; -- unsigned required_fields_bitmap_len; -- unsigned char required_fields_bitmap_stack[16]; -- unsigned char *required_fields_bitmap = required_fields_bitmap_stack; -- protobuf_c_boolean required_fields_bitmap_alloced = FALSE; -- -- ASSERT_IS_MESSAGE_DESCRIPTOR(desc); -- -- if (allocator == NULL) -- allocator = &protobuf_c__allocator; -- -- rv = do_alloc(allocator, desc->sizeof_message); -- if (!rv) -- return (NULL); -- scanned_member_slabs[0] = first_member_slab; -- -- required_fields_bitmap_len = (desc->n_fields + 7) / 8; -- if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) { -- required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len); -- if (!required_fields_bitmap) { -- do_free(allocator, rv); -- return (NULL); -- } -- required_fields_bitmap_alloced = TRUE; -- } -- memset(required_fields_bitmap, 0, required_fields_bitmap_len); -- -- /* -- * Generated code always defines "message_init". However, we provide a -- * fallback for (1) users of old protobuf-c generated-code that do not -- * provide the function, and (2) descriptors constructed from some other -- * source (most likely, direct construction from the .proto file). -- */ -- if (desc->message_init != NULL) -- protobuf_c_message_init(desc, rv); -- else -- message_init_generic(desc, rv); -- -- while (rem > 0) { -- uint32_t tag; -- ProtobufCWireType wire_type; -- size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type); -- const ProtobufCFieldDescriptor *field; -- ScannedMember tmp; -- -- if (used == 0) { -- PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u", -- (unsigned) (at - data)); -- goto error_cleanup_during_scan; -- } -- /* -- * \todo Consider optimizing for field[1].id == tag, if field[1] -- * exists! -- */ -- if (last_field == NULL || last_field->id != tag) { -- /* lookup field */ -- int field_index = -- int_range_lookup(desc->n_field_ranges, -- desc->field_ranges, -- tag); -- if (field_index < 0) { -- field = NULL; -- n_unknown++; -- } else { -- field = desc->fields + field_index; -- last_field = field; -- last_field_index = field_index; -- } -- } else { -- field = last_field; -- } -- -- if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED) -- REQUIRED_FIELD_BITMAP_SET(last_field_index); -- -- at += used; -- rem -= used; -- tmp.tag = tag; -- tmp.wire_type = wire_type; -- tmp.field = field; -- tmp.data = at; -- tmp.length_prefix_len = 0; -- -- switch (wire_type) { -- case PROTOBUF_C_WIRE_TYPE_VARINT: { -- unsigned max_len = rem < 10 ? rem : 10; -- unsigned i; -- -- for (i = 0; i < max_len; i++) -- if ((at[i] & 0x80) == 0) -- break; -- if (i == max_len) { -- PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u", -- (unsigned) (at - data)); -- goto error_cleanup_during_scan; -- } -- tmp.len = i + 1; -- break; -- } -- case PROTOBUF_C_WIRE_TYPE_64BIT: -- if (rem < 8) { -- PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u", -- (unsigned) (at - data)); -- goto error_cleanup_during_scan; -- } -- tmp.len = 8; -- break; -- case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: { -- size_t pref_len; -- -- tmp.len = scan_length_prefixed_data(rem, at, &pref_len); -- if (tmp.len == 0) { -- /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ -- goto error_cleanup_during_scan; -- } -- tmp.length_prefix_len = pref_len; -- break; -- } -- case PROTOBUF_C_WIRE_TYPE_32BIT: -- if (rem < 4) { -- PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u", -- (unsigned) (at - data)); -- goto error_cleanup_during_scan; -- } -- tmp.len = 4; -- break; -- default: -- PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u", -- wire_type, (unsigned) (at - data)); -- goto error_cleanup_during_scan; -- } -- -- if (in_slab_index == (1U << -- (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2))) -- { -- size_t size; -- -- in_slab_index = 0; -- if (which_slab == MAX_SCANNED_MEMBER_SLAB) { -- PROTOBUF_C_UNPACK_ERROR("too many fields"); -- goto error_cleanup_during_scan; -- } -- which_slab++; -- size = sizeof(ScannedMember) -- << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2); -- scanned_member_slabs[which_slab] = do_alloc(allocator, size); -- if (scanned_member_slabs[which_slab] == NULL) -- goto error_cleanup_during_scan; -- } -- scanned_member_slabs[which_slab][in_slab_index++] = tmp; -- -- if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) { -- size_t *n = STRUCT_MEMBER_PTR(size_t, rv, -- field->quantifier_offset); -- if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && -- (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || -- is_packable_type(field->type))) -- { -- size_t count; -- if (!count_packed_elements(field->type, -- tmp.len - -- tmp.length_prefix_len, -- tmp.data + -- tmp.length_prefix_len, -- &count)) -- { -- PROTOBUF_C_UNPACK_ERROR("counting packed elements"); -- goto error_cleanup_during_scan; -- } -- *n += count; -- } else { -- *n += 1; -- } -- } -- -- at += tmp.len; -- rem -= tmp.len; -- } -- -- /* allocate space for repeated fields, also check that all required fields have been set */ -- for (f = 0; f < desc->n_fields; f++) { -- const ProtobufCFieldDescriptor *field = desc->fields + f; -- if (field->label == PROTOBUF_C_LABEL_REPEATED) { -- size_t siz = -- sizeof_elt_in_repeated_array(field->type); -- size_t *n_ptr = -- STRUCT_MEMBER_PTR(size_t, rv, -- field->quantifier_offset); -- if (*n_ptr != 0) { -- unsigned n = *n_ptr; -- *n_ptr = 0; -- assert(rv->descriptor != NULL); --#define CLEAR_REMAINING_N_PTRS() \ -- for(f++;f < desc->n_fields; f++) \ -- { \ -- field = desc->fields + f; \ -- if (field->label == PROTOBUF_C_LABEL_REPEATED) \ -- STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \ -- } -- void *a = do_alloc(allocator, siz * n); -- if (!a) { -- CLEAR_REMAINING_N_PTRS(); -- goto error_cleanup; -- } -- STRUCT_MEMBER(void *, rv, field->offset) = a; -- } -- } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -- if (field->default_value == NULL && -- !REQUIRED_FIELD_BITMAP_IS_SET(f)) -- { -- CLEAR_REMAINING_N_PTRS(); -- PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'", -- desc->name, field->name); -- goto error_cleanup; -- } -- } -- } --#undef CLEAR_REMAINING_N_PTRS -- -- /* allocate space for unknown fields */ -- if (n_unknown) { -- rv->unknown_fields = do_alloc(allocator, -- n_unknown * sizeof(ProtobufCMessageUnknownField)); -- if (rv->unknown_fields == NULL) -- goto error_cleanup; -- } -- -- /* do real parsing */ -- for (i_slab = 0; i_slab <= which_slab; i_slab++) { -- unsigned max = (i_slab == which_slab) ? -- in_slab_index : (1U << (i_slab + 4)); -- ScannedMember *slab = scanned_member_slabs[i_slab]; -- unsigned j; -- -- for (j = 0; j < max; j++) { -- if (!parse_member(slab + j, rv, allocator)) { -- PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s", -- slab->field ? slab->field->name : "*unknown-field*", -- desc->name); -- goto error_cleanup; -- } -- } -- } -- -- /* cleanup */ -- for (j = 1; j <= which_slab; j++) -- do_free(allocator, scanned_member_slabs[j]); -- if (required_fields_bitmap_alloced) -- do_free(allocator, required_fields_bitmap); -- return rv; -- --error_cleanup: -- protobuf_c_message_free_unpacked(rv, allocator); -- for (j = 1; j <= which_slab; j++) -- do_free(allocator, scanned_member_slabs[j]); -- if (required_fields_bitmap_alloced) -- do_free(allocator, required_fields_bitmap); -- return NULL; -- --error_cleanup_during_scan: -- do_free(allocator, rv); -- for (j = 1; j <= which_slab; j++) -- do_free(allocator, scanned_member_slabs[j]); -- if (required_fields_bitmap_alloced) -- do_free(allocator, required_fields_bitmap); -- return NULL; --} -- --void --protobuf_c_message_free_unpacked(ProtobufCMessage *message, -- ProtobufCAllocator *allocator) --{ -- const ProtobufCMessageDescriptor *desc = message->descriptor; -- unsigned f; -- -- ASSERT_IS_MESSAGE(message); -- if (allocator == NULL) -- allocator = &protobuf_c__allocator; -- message->descriptor = NULL; -- for (f = 0; f < desc->n_fields; f++) { -- if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { -- size_t n = STRUCT_MEMBER(size_t, -- message, -- desc->fields[f].quantifier_offset); -- void *arr = STRUCT_MEMBER(void *, -- message, -- desc->fields[f].offset); -- -- if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { -- unsigned i; -- for (i = 0; i < n; i++) -- do_free(allocator, ((char **) arr)[i]); -- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { -- unsigned i; -- for (i = 0; i < n; i++) -- do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); -- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { -- unsigned i; -- for (i = 0; i < n; i++) -- protobuf_c_message_free_unpacked( -- ((ProtobufCMessage **) arr)[i], -- allocator -- ); -- } -- if (arr != NULL) -- do_free(allocator, arr); -- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { -- char *str = STRUCT_MEMBER(char *, message, -- desc->fields[f].offset); -- -- if (str && str != desc->fields[f].default_value) -- do_free(allocator, str); -- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { -- void *data = STRUCT_MEMBER(ProtobufCBinaryData, message, -- desc->fields[f].offset).data; -- const ProtobufCBinaryData *default_bd; -- -- default_bd = desc->fields[f].default_value; -- if (data != NULL && -- (default_bd == NULL || -- default_bd->data != data)) -- { -- do_free(allocator, data); -- } -- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { -- ProtobufCMessage *sm; -- -- sm = STRUCT_MEMBER(ProtobufCMessage *, message, -- desc->fields[f].offset); -- if (sm && sm != desc->fields[f].default_value) -- protobuf_c_message_free_unpacked(sm, allocator); -- } -- } -- -- for (f = 0; f < message->n_unknown_fields; f++) -- do_free(allocator, message->unknown_fields[f].data); -- if (message->unknown_fields != NULL) -- do_free(allocator, message->unknown_fields); -- -- do_free(allocator, message); --} -- --void --protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor, -- void *message) --{ -- descriptor->message_init((ProtobufCMessage *) (message)); --} -- --protobuf_c_boolean --protobuf_c_message_check(const ProtobufCMessage *message) --{ -- if (!message || -- !message->descriptor || -- message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) -- { -- return FALSE; -- } -- -- unsigned i; -- for (i = 0; i < message->descriptor->n_fields; i++) { -- const ProtobufCFieldDescriptor *f = message->descriptor->fields + i; -- ProtobufCType type = f->type; -- ProtobufCLabel label = f->label; -- void *field = STRUCT_MEMBER_P (message, f->offset); -- -- if (label == PROTOBUF_C_LABEL_REPEATED) { -- size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset); -- -- if (*quantity > 0 && *(void **) field == NULL) { -- return FALSE; -- } -- -- if (type == PROTOBUF_C_TYPE_MESSAGE) { -- ProtobufCMessage **submessage = *(ProtobufCMessage ***) field; -- unsigned j; -- for (j = 0; j < *quantity; j++) { -- if (!protobuf_c_message_check(submessage[j])) -- return FALSE; -- } -- } else if (type == PROTOBUF_C_TYPE_STRING) { -- char **string = *(char ***) field; -- unsigned j; -- for (j = 0; j < *quantity; j++) { -- if (!string[j]) -- return FALSE; -- } -- } else if (type == PROTOBUF_C_TYPE_BYTES) { -- ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field; -- unsigned j; -- for (j = 0; j < *quantity; j++) { -- if (bd[j].len > 0 && bd[j].data == NULL) -- return FALSE; -- } -- } -- -- } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */ -- -- if (type == PROTOBUF_C_TYPE_MESSAGE) { -- ProtobufCMessage *submessage = *(ProtobufCMessage **) field; -- if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) { -- if (!protobuf_c_message_check(submessage)) -- return FALSE; -- } -- } else if (type == PROTOBUF_C_TYPE_STRING) { -- char *string = *(char **) field; -- if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL) -- return FALSE; -- } else if (type == PROTOBUF_C_TYPE_BYTES) { -- protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset); -- ProtobufCBinaryData *bd = field; -- if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) { -- if (bd->len > 0 && bd->data == NULL) -- return FALSE; -- } -- } -- } -- } -- -- return TRUE; --} -- --/* === services === */ -- --typedef void (*GenericHandler) (void *service, -- const ProtobufCMessage *input, -- ProtobufCClosure closure, -- void *closure_data); --void --protobuf_c_service_invoke_internal(ProtobufCService *service, -- unsigned method_index, -- const ProtobufCMessage *input, -- ProtobufCClosure closure, -- void *closure_data) --{ -- GenericHandler *handlers; -- GenericHandler handler; -- -- /* -- * Verify that method_index is within range. If this fails, you are -- * likely invoking a newly added method on an old service. (Although -- * other memory corruption bugs can cause this assertion too.) -- */ -- assert(method_index < service->descriptor->n_methods); -- -- /* -- * Get the array of virtual methods (which are enumerated by the -- * generated code). -- */ -- handlers = (GenericHandler *) (service + 1); -- -- /* -- * Get our method and invoke it. -- * \todo Seems like handler == NULL is a situation that needs handling. -- */ -- handler = handlers[method_index]; -- (*handler)(service, input, closure, closure_data); --} -- --void --protobuf_c_service_generated_init(ProtobufCService *service, -- const ProtobufCServiceDescriptor *descriptor, -- ProtobufCServiceDestroy destroy) --{ -- ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); -- service->descriptor = descriptor; -- service->destroy = destroy; -- service->invoke = protobuf_c_service_invoke_internal; -- memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); --} -- --void protobuf_c_service_destroy(ProtobufCService *service) --{ -- service->destroy(service); --} -- --/* --- querying the descriptors --- */ -- --const ProtobufCEnumValue * --protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc, -- const char *name) --{ -- unsigned start = 0; -- unsigned count = desc->n_value_names; -- -- while (count > 1) { -- unsigned mid = start + count / 2; -- int rv = strcmp(desc->values_by_name[mid].name, name); -- if (rv == 0) -- return desc->values + desc->values_by_name[mid].index; -- else if (rv < 0) { -- count = start + count - (mid + 1); -- start = mid + 1; -- } else -- count = mid - start; -- } -- if (count == 0) -- return NULL; -- if (strcmp(desc->values_by_name[start].name, name) == 0) -- return desc->values + desc->values_by_name[start].index; -- return NULL; --} -- --const ProtobufCEnumValue * --protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc, -- int value) --{ -- int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value); -- if (rv < 0) -- return NULL; -- return desc->values + rv; --} -- --const ProtobufCFieldDescriptor * --protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc, -- const char *name) --{ -- unsigned start = 0; -- unsigned count = desc->n_fields; -- const ProtobufCFieldDescriptor *field; -- -- while (count > 1) { -- unsigned mid = start + count / 2; -- int rv; -- field = desc->fields + desc->fields_sorted_by_name[mid]; -- rv = strcmp(field->name, name); -- if (rv == 0) -- return field; -- else if (rv < 0) { -- count = start + count - (mid + 1); -- start = mid + 1; -- } else -- count = mid - start; -- } -- if (count == 0) -- return NULL; -- field = desc->fields + desc->fields_sorted_by_name[start]; -- if (strcmp(field->name, name) == 0) -- return field; -- return NULL; --} -- --const ProtobufCFieldDescriptor * --protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc, -- unsigned value) --{ -- int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value); -- if (rv < 0) -- return NULL; -- return desc->fields + rv; --} -- --const ProtobufCMethodDescriptor * --protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc, -- const char *name) --{ -- unsigned start = 0; -- unsigned count = desc->n_methods; -- -- while (count > 1) { -- unsigned mid = start + count / 2; -- unsigned mid_index = desc->method_indices_by_name[mid]; -- const char *mid_name = desc->methods[mid_index].name; -- int rv = strcmp(mid_name, name); -- -- if (rv == 0) -- return desc->methods + desc->method_indices_by_name[mid]; -- if (rv < 0) { -- count = start + count - (mid + 1); -- start = mid + 1; -- } else { -- count = mid - start; -- } -- } -- if (count == 0) -- return NULL; -- if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0) -- return desc->methods + desc->method_indices_by_name[start]; -- return NULL; --} -diff --git a/src/protobuf/google/protobuf-c/protobuf-c.h b/src/protobuf/google/protobuf-c/protobuf-c.h -deleted file mode 100644 -index 593df2d..0000000 ---- a/src/protobuf/google/protobuf-c/protobuf-c.h -+++ /dev/null -@@ -1,1079 +0,0 @@ --/* -- * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. -- * All rights reserved. -- * -- * Redistribution and use in source and binary forms, with or without -- * modification, are permitted provided that the following conditions are -- * met: -- * -- * * Redistributions of source code must retain the above copyright -- * notice, this list of conditions and the following disclaimer. -- * -- * * Redistributions in binary form must reproduce the above -- * copyright notice, this list of conditions and the following disclaimer -- * in the documentation and/or other materials provided with the -- * distribution. -- * -- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- */ -- --/*! \file -- * \mainpage Introduction -- * -- * This is [protobuf-c], a C implementation of [Protocol Buffers]. -- * -- * This file defines the public API for the `libprotobuf-c` support library. -- * This API includes interfaces that can be used directly by client code as well -- * as the interfaces used by the code generated by the `protoc-c` compiler. -- * -- * The `libprotobuf-c` support library performs the actual serialization and -- * deserialization of Protocol Buffers messages. It interacts with structures, -- * definitions, and metadata generated by the `protoc-c` compiler from .proto -- * files. -- * -- * \authors Dave Benson and the `protobuf-c` authors. -- * -- * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. -- * -- * [protobuf-c]: https://github.com/protobuf-c/protobuf-c -- * [Protocol Buffers]: https://developers.google.com/protocol-buffers/ -- * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause -- * -- * \page gencode Generated Code -- * -- * For each enum, we generate a C enum. For each message, we generate a C -- * structure which can be cast to a `ProtobufCMessage`. -- * -- * For each enum and message, we generate a descriptor object that allows us to -- * implement a kind of reflection on the structures. -- * -- * First, some naming conventions: -- * -- * - The name of the type for enums and messages and services is camel case -- * (meaning WordsAreCrammedTogether) except that double underscores are used -- * to delimit scopes. For example, the following `.proto` file: -- * --~~~{.proto} -- package foo.bar; -- message BazBah { -- optional int32 val = 1; -- } --~~~ -- * -- * would generate a C type `Foo__Bar__BazBah`. -- * -- * - Identifiers for functions and globals are all lowercase, with camel case -- * words separated by single underscores. For example, one of the function -- * prototypes generated by `protoc-c` for the above example: -- * --~~~{.c} --Foo__Bar__BazBah * -- foo__bar__baz_bah__unpack -- (ProtobufCAllocator *allocator, -- size_t len, -- const uint8_t *data); --~~~ -- * -- * - Identifiers for enum values contain an uppercase prefix which embeds the -- * package name and the enum type name. -- * -- * - A double underscore is used to separate further components of identifier -- * names. -- * -- * For example, in the name of the unpack function above, the package name -- * `foo.bar` has become `foo__bar`, the message name BazBah has become -- * `baz_bah`, and the method name is `unpack`. These are all joined with double -- * underscores to form the C identifier `foo__bar__baz_bah__unpack`. -- * -- * We also generate descriptor objects for messages and enums. These are -- * declared in the `.pb-c.h` files: -- * --~~~{.c} --extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor; --~~~ -- * -- * The message structures all begin with `ProtobufCMessageDescriptor *` which is -- * sufficient to allow them to be cast to `ProtobufCMessage`. -- * -- * For each message defined in a `.proto` file, we generate a number of -- * functions. Each function name contains a prefix based on the package name and -- * message name in order to make it a unique C identifier. -- * -- * - `unpack()`. Unpacks data for a particular message format. Note that the -- * `allocator` parameter is usually `NULL` to indicate that the system's -- * `malloc()` and `free()` functions should be used for dynamically allocating -- * memory. -- * --~~~{.c} --Foo__Bar__BazBah * -- foo__bar__baz_bah__unpack -- (ProtobufCAllocator *allocator, -- size_t len, -- const uint8_t *data); --~~~ -- * -- * - `free_unpacked()`. Frees a message object obtained with the `unpack()` -- * method. -- * --~~~{.c} --void foo__bar__baz_bah__free_unpacked -- (Foo__Bar__BazBah *message, -- ProtobufCAllocator *allocator); --~~~ -- * -- * - `get_packed_size()`. Calculates the length in bytes of the serialized -- * representation of the message object. -- * --~~~{.c} --size_t foo__bar__baz_bah__get_packed_size -- (const Foo__Bar__BazBah *message); --~~~ -- * -- * - `pack()`. Pack a message object into a preallocated buffer. Assumes that -- * the buffer is large enough. (Use `get_packed_size()` first.) -- * --~~~{.c} --size_t foo__bar__baz_bah__pack -- (const Foo__Bar__BazBah *message, -- uint8_t *out); --~~~ -- * -- * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an -- * object which defines an "append bytes" callback to consume data as it is -- * serialized. -- * --~~~{.c} --size_t foo__bar__baz_bah__pack_to_buffer -- (const Foo__Bar__BazBah *message, -- ProtobufCBuffer *buffer); --~~~ -- * -- * \page pack Packing and unpacking messages -- * -- * To pack a message, first compute the packed size of the message with -- * protobuf_c_message_get_packed_size(), then allocate a buffer of at least -- * that size, then call protobuf_c_message_pack(). -- * -- * Alternatively, a message can be serialized without calculating the final size -- * first. Use the protobuf_c_message_pack_to_buffer() function and provide a -- * ProtobufCBuffer object which implements an "append" method that consumes -- * data. -- * -- * To unpack a message, call the protobuf_c_message_unpack() function. The -- * result can be cast to an object of the type that matches the descriptor for -- * the message. -- * -- * The result of unpacking a message should be freed with -- * protobuf_c_message_free_unpacked(). -- */ -- --#ifndef PROTOBUF_C_H --#define PROTOBUF_C_H -- --#include --#include --#include --#include -- --#ifdef __cplusplus --# define PROTOBUF_C__BEGIN_DECLS extern "C" { --# define PROTOBUF_C__END_DECLS } --#else --# define PROTOBUF_C__BEGIN_DECLS --# define PROTOBUF_C__END_DECLS --#endif -- --PROTOBUF_C__BEGIN_DECLS -- --#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB) --# ifdef PROTOBUF_C_EXPORT --# define PROTOBUF_C__API __declspec(dllexport) --# else --# define PROTOBUF_C__API __declspec(dllimport) --# endif --#else --# define PROTOBUF_C__API --#endif -- --#if !defined(PROTOBUF_C__NO_DEPRECATED) --# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) --# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__)) --# endif --#else --# define PROTOBUF_C__DEPRECATED --#endif -- --#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE -- #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \ -- , _##enum_name##_IS_INT_SIZE = INT_MAX --#endif -- --#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3 --#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9 --#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af -- --/** -- * \defgroup api Public API -- * -- * This is the public API for `libprotobuf-c`. These interfaces are stable and -- * subject to Semantic Versioning guarantees. -- * -- * @{ -- */ -- --/** -- * Values for the `flags` word in `ProtobufCFieldDescriptor`. -- */ --typedef enum { -- /** Set if the field is repeated and marked with the `packed` option. */ -- PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0), -- -- /** Set if the field is marked with the `deprecated` option. */ -- PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1), --} ProtobufCFieldFlag; -- --/** -- * Message field rules. -- * -- * \see [Defining A Message Type] in the Protocol Buffers documentation. -- * -- * [Defining A Message Type]: -- * https://developers.google.com/protocol-buffers/docs/proto#simple -- */ --typedef enum { -- /** A well-formed message must have exactly one of this field. */ -- PROTOBUF_C_LABEL_REQUIRED, -- -- /** -- * A well-formed message can have zero or one of this field (but not -- * more than one). -- */ -- PROTOBUF_C_LABEL_OPTIONAL, -- -- /** -- * This field can be repeated any number of times (including zero) in a -- * well-formed message. The order of the repeated values will be -- * preserved. -- */ -- PROTOBUF_C_LABEL_REPEATED, --} ProtobufCLabel; -- --/** -- * Field value types. -- * -- * \see [Scalar Value Types] in the Protocol Buffers documentation. -- * -- * [Scalar Value Types]: -- * https://developers.google.com/protocol-buffers/docs/proto#scalar -- */ --typedef enum { -- PROTOBUF_C_TYPE_INT32, /**< int32 */ -- PROTOBUF_C_TYPE_SINT32, /**< signed int32 */ -- PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */ -- PROTOBUF_C_TYPE_INT64, /**< int64 */ -- PROTOBUF_C_TYPE_SINT64, /**< signed int64 */ -- PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */ -- PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */ -- PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */ -- PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */ -- PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */ -- PROTOBUF_C_TYPE_FLOAT, /**< float */ -- PROTOBUF_C_TYPE_DOUBLE, /**< double */ -- PROTOBUF_C_TYPE_BOOL, /**< boolean */ -- PROTOBUF_C_TYPE_ENUM, /**< enumerated type */ -- PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */ -- PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */ -- PROTOBUF_C_TYPE_MESSAGE, /**< nested message */ --} ProtobufCType; -- --/** -- * Field wire types. -- * -- * \see [Message Structure] in the Protocol Buffers documentation. -- * -- * [Message Structure]: -- * https://developers.google.com/protocol-buffers/docs/encoding#structure -- */ --typedef enum { -- PROTOBUF_C_WIRE_TYPE_VARINT = 0, -- PROTOBUF_C_WIRE_TYPE_64BIT = 1, -- PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2, -- /* "Start group" and "end group" wire types are unsupported. */ -- PROTOBUF_C_WIRE_TYPE_32BIT = 5, --} ProtobufCWireType; -- --struct ProtobufCAllocator; --struct ProtobufCBinaryData; --struct ProtobufCBuffer; --struct ProtobufCBufferSimple; --struct ProtobufCEnumDescriptor; --struct ProtobufCEnumValue; --struct ProtobufCEnumValueIndex; --struct ProtobufCFieldDescriptor; --struct ProtobufCIntRange; --struct ProtobufCMessage; --struct ProtobufCMessageDescriptor; --struct ProtobufCMessageUnknownField; --struct ProtobufCMethodDescriptor; --struct ProtobufCService; --struct ProtobufCServiceDescriptor; -- --typedef struct ProtobufCAllocator ProtobufCAllocator; --typedef struct ProtobufCBinaryData ProtobufCBinaryData; --typedef struct ProtobufCBuffer ProtobufCBuffer; --typedef struct ProtobufCBufferSimple ProtobufCBufferSimple; --typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor; --typedef struct ProtobufCEnumValue ProtobufCEnumValue; --typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex; --typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor; --typedef struct ProtobufCIntRange ProtobufCIntRange; --typedef struct ProtobufCMessage ProtobufCMessage; --typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor; --typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField; --typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor; --typedef struct ProtobufCService ProtobufCService; --typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor; -- --/** Boolean type. */ --typedef int protobuf_c_boolean; -- --typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data); --typedef void (*ProtobufCMessageInit)(ProtobufCMessage *); --typedef void (*ProtobufCServiceDestroy)(ProtobufCService *); -- --/** -- * Structure for defining a custom memory allocator. -- */ --struct ProtobufCAllocator { -- /** Function to allocate memory. */ -- void *(*alloc)(void *allocator_data, size_t size); -- -- /** Function to free memory. */ -- void (*free)(void *allocator_data, void *pointer); -- -- /** Opaque pointer passed to `alloc` and `free` functions. */ -- void *allocator_data; --}; -- --/** -- * Structure for the protobuf `bytes` scalar type. -- * -- * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of -- * bytes. It may contain embedded `NUL` characters and is not required to be -- * `NUL`-terminated. -- */ --struct ProtobufCBinaryData { -- size_t len; /**< Number of bytes in the `data` field. */ -- uint8_t *data; /**< Data bytes. */ --}; -- --/** -- * Structure for defining a virtual append-only buffer. Used by -- * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized -- * bytes. -- * -- * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to -- * write to a `FILE` object: -- * --~~~{.c} --typedef struct { -- ProtobufCBuffer base; -- FILE *fp; --} BufferAppendToFile; -- --static void --my_buffer_file_append(ProtobufCBuffer *buffer, -- size_t len, -- const uint8_t *data) --{ -- BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer; -- fwrite(data, len, 1, file_buf->fp); // XXX: No error handling! --} --~~~ -- * -- * To use this new type of ProtobufCBuffer, it could be called as follows: -- * --~~~{.c} --... --BufferAppendToFile tmp = {0}; --tmp.base.append = my_buffer_file_append; --tmp.fp = fp; --protobuf_c_message_pack_to_buffer(&message, &tmp); --... --~~~ -- */ --struct ProtobufCBuffer { -- /** Append function. Consumes the `len` bytes stored at `data`. */ -- void (*append)(ProtobufCBuffer *buffer, -- size_t len, -- const uint8_t *data); --}; -- --/** -- * Simple buffer "subclass" of `ProtobufCBuffer`. -- * -- * A `ProtobufCBufferSimple` object is declared on the stack and uses a -- * scratch buffer provided by the user for the initial allocation. It performs -- * exponential resizing, using dynamically allocated memory. A -- * `ProtobufCBufferSimple` object can be created and used as follows: -- * --~~~{.c} --uint8_t pad[128]; --ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad); --ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple; --~~~ -- * -- * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a -- * message has been serialized to a `ProtobufCBufferSimple` object, the -- * serialized data bytes can be accessed from the `.data` field. -- * -- * To free the memory allocated by a `ProtobufCBufferSimple` object, if any, -- * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example: -- * --~~~{.c} --PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple); --~~~ -- * -- * \see PROTOBUF_C_BUFFER_SIMPLE_INIT -- * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR -- */ --struct ProtobufCBufferSimple { -- /** "Base class". */ -- ProtobufCBuffer base; -- /** Number of bytes allocated in `data`. */ -- size_t alloced; -- /** Number of bytes currently stored in `data`. */ -- size_t len; -- /** Data bytes. */ -- uint8_t *data; -- /** Whether `data` must be freed. */ -- protobuf_c_boolean must_free_data; -- /** Allocator to use. May be NULL to indicate the system allocator. */ -- ProtobufCAllocator *allocator; --}; -- --/** -- * Describes an enumeration as a whole, with all of its values. -- */ --struct ProtobufCEnumDescriptor { -- /** Magic value checked to ensure that the API is used correctly. */ -- uint32_t magic; -- -- /** The qualified name (e.g., "namespace.Type"). */ -- const char *name; -- /** The unqualified name as given in the .proto file (e.g., "Type"). */ -- const char *short_name; -- /** Identifier used in generated C code. */ -- const char *c_name; -- /** The dot-separated namespace. */ -- const char *package_name; -- -- /** Number elements in `values`. */ -- unsigned n_values; -- /** Array of distinct values, sorted by numeric value. */ -- const ProtobufCEnumValue *values; -- -- /** Number of elements in `values_by_name`. */ -- unsigned n_value_names; -- /** Array of named values, including aliases, sorted by name. */ -- const ProtobufCEnumValueIndex *values_by_name; -- -- /** Number of elements in `value_ranges`. */ -- unsigned n_value_ranges; -- /** Value ranges, for faster lookups by numeric value. */ -- const ProtobufCIntRange *value_ranges; -- -- /** Reserved for future use. */ -- void *reserved1; -- /** Reserved for future use. */ -- void *reserved2; -- /** Reserved for future use. */ -- void *reserved3; -- /** Reserved for future use. */ -- void *reserved4; --}; -- --/** -- * Represents a single value of an enumeration. -- */ --struct ProtobufCEnumValue { -- /** The string identifying this value in the .proto file. */ -- const char *name; -- -- /** The string identifying this value in generated C code. */ -- const char *c_name; -- -- /** The numeric value assigned in the .proto file. */ -- int value; --}; -- --/** -- * Used by `ProtobufCEnumDescriptor` to look up enum values. -- */ --struct ProtobufCEnumValueIndex { -- /** Name of the enum value. */ -- const char *name; -- /** Index into values[] array. */ -- unsigned index; --}; -- --/** -- * Describes a single field in a message. -- */ --struct ProtobufCFieldDescriptor { -- /** Name of the field as given in the .proto file. */ -- const char *name; -- -- /** Tag value of the field as given in the .proto file. */ -- uint32_t id; -- -- /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */ -- ProtobufCLabel label; -- -- /** The type of the field. */ -- ProtobufCType type; -- -- /** -- * The offset in bytes of the message's C structure's quantifier field -- * (the `has_MEMBER` field for optional members or the `n_MEMBER` field -- * for repeated members. -- */ -- unsigned quantifier_offset; -- -- /** -- * The offset in bytes into the message's C structure for the member -- * itself. -- */ -- unsigned offset; -- -- /** -- * A type-specific descriptor. -- * -- * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the -- * corresponding `ProtobufCEnumDescriptor`. -- * -- * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to -- * the corresponding `ProtobufCMessageDescriptor`. -- * -- * Otherwise this field is NULL. -- */ -- const void *descriptor; /* for MESSAGE and ENUM types */ -- -- /** The default value for this field, if defined. May be NULL. */ -- const void *default_value; -- -- /** -- * A flag word. Zero or more of the bits defined in the -- * `ProtobufCFieldFlag` enum may be set. -- */ -- uint32_t flags; -- -- /** Reserved for future use. */ -- unsigned reserved_flags; -- /** Reserved for future use. */ -- void *reserved2; -- /** Reserved for future use. */ -- void *reserved3; --}; -- --/** -- * Helper structure for optimizing int => index lookups in the case -- * where the keys are mostly consecutive values, as they presumably are for -- * enums and fields. -- * -- * The data structures requires that the values in the original array are -- * sorted. -- */ --struct ProtobufCIntRange { -- int start_value; -- unsigned orig_index; -- /* -- * NOTE: the number of values in the range can be inferred by looking -- * at the next element's orig_index. A dummy element is added to make -- * this simple. -- */ --}; -- --/** -- * An instance of a message. -- * -- * `ProtobufCMessage` is a light-weight "base class" for all messages. -- * -- * In particular, `ProtobufCMessage` doesn't have any allocation policy -- * associated with it. That's because it's common to create `ProtobufCMessage` -- * objects on the stack. In fact, that's what we recommend for sending messages. -- * If the object is allocated from the stack, you can't really have a memory -- * leak. -- * -- * This means that calls to functions like protobuf_c_message_unpack() which -- * return a `ProtobufCMessage` must be paired with a call to a free function, -- * like protobuf_c_message_free_unpacked(). -- */ --struct ProtobufCMessage { -- /** The descriptor for this message type. */ -- const ProtobufCMessageDescriptor *descriptor; -- /** The number of elements in `unknown_fields`. */ -- unsigned n_unknown_fields; -- /** The fields that weren't recognized by the parser. */ -- ProtobufCMessageUnknownField *unknown_fields; --}; -- --/** -- * Describes a message. -- */ --struct ProtobufCMessageDescriptor { -- /** Magic value checked to ensure that the API is used correctly. */ -- uint32_t magic; -- -- /** The qualified name (e.g., "namespace.Type"). */ -- const char *name; -- /** The unqualified name as given in the .proto file (e.g., "Type"). */ -- const char *short_name; -- /** Identifier used in generated C code. */ -- const char *c_name; -- /** The dot-separated namespace. */ -- const char *package_name; -- -- /** -- * Size in bytes of the C structure representing an instance of this -- * type of message. -- */ -- size_t sizeof_message; -- -- /** Number of elements in `fields`. */ -- unsigned n_fields; -- /** Field descriptors, sorted by tag number. */ -- const ProtobufCFieldDescriptor *fields; -- /** Used for looking up fields by name. */ -- const unsigned *fields_sorted_by_name; -- -- /** Number of elements in `field_ranges`. */ -- unsigned n_field_ranges; -- /** Used for looking up fields by id. */ -- const ProtobufCIntRange *field_ranges; -- -- /** Message initialisation function. */ -- ProtobufCMessageInit message_init; -- -- /** Reserved for future use. */ -- void *reserved1; -- /** Reserved for future use. */ -- void *reserved2; -- /** Reserved for future use. */ -- void *reserved3; --}; -- --/** -- * An unknown message field. -- */ --struct ProtobufCMessageUnknownField { -- /** The tag number. */ -- uint32_t tag; -- /** The wire type of the field. */ -- ProtobufCWireType wire_type; -- /** Number of bytes in `data`. */ -- size_t len; -- /** Field data. */ -- uint8_t *data; --}; -- --/** -- * Method descriptor. -- */ --struct ProtobufCMethodDescriptor { -- /** Method name. */ -- const char *name; -- /** Input message descriptor. */ -- const ProtobufCMessageDescriptor *input; -- /** Output message descriptor. */ -- const ProtobufCMessageDescriptor *output; --}; -- --/** -- * Service. -- */ --struct ProtobufCService { -- /** Service descriptor. */ -- const ProtobufCServiceDescriptor *descriptor; -- /** Function to invoke the service. */ -- void (*invoke)(ProtobufCService *service, -- unsigned method_index, -- const ProtobufCMessage *input, -- ProtobufCClosure closure, -- void *closure_data); -- /** Function to destroy the service. */ -- void (*destroy)(ProtobufCService *service); --}; -- --/** -- * Service descriptor. -- */ --struct ProtobufCServiceDescriptor { -- /** Magic value checked to ensure that the API is used correctly. */ -- uint32_t magic; -- -- /** Service name. */ -- const char *name; -- /** Short version of service name. */ -- const char *short_name; -- /** C identifier for the service name. */ -- const char *c_name; -- /** Package name. */ -- const char *package; -- /** Number of elements in `methods`. */ -- unsigned n_methods; -- /** Method descriptors, in the order defined in the .proto file. */ -- const ProtobufCMethodDescriptor *methods; -- /** Sort index of methods. */ -- const unsigned *method_indices_by_name; --}; -- --/** -- * Get the version of the protobuf-c library. Note that this is the version of -- * the library linked against, not the version of the headers compiled against. -- * -- * \return A string containing the version number of protobuf-c. -- */ --PROTOBUF_C__API --const char * --protobuf_c_version(void); -- --/** -- * Get the version of the protobuf-c library. Note that this is the version of -- * the library linked against, not the version of the headers compiled against. -- * -- * \return A 32 bit unsigned integer containing the version number of -- * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH. -- */ --PROTOBUF_C__API --uint32_t --protobuf_c_version_number(void); -- --/** -- * The version of the protobuf-c headers, represented as a string using the same -- * format as protobuf_c_version(). -- */ --#define PROTOBUF_C_VERSION "1.0.0" -- --/** -- * The version of the protobuf-c headers, represented as an integer using the -- * same format as protobuf_c_version_number(). -- */ --#define PROTOBUF_C_VERSION_NUMBER 1000000 -- --/** -- * The minimum protoc-c version which works with the current version of the -- * protobuf-c headers. -- */ --#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000 -- --/** -- * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name. -- * -- * \param desc -- * The `ProtobufCEnumDescriptor` object. -- * \param name -- * The `name` field from the corresponding `ProtobufCEnumValue` object to -- * match. -- * \return -- * A `ProtobufCEnumValue` object. -- * \retval NULL -- * If not found. -- */ --PROTOBUF_C__API --const ProtobufCEnumValue * --protobuf_c_enum_descriptor_get_value_by_name( -- const ProtobufCEnumDescriptor *desc, -- const char *name); -- --/** -- * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric -- * value. -- * -- * \param desc -- * The `ProtobufCEnumDescriptor` object. -- * \param value -- * The `value` field from the corresponding `ProtobufCEnumValue` object to -- * match. -- * -- * \return -- * A `ProtobufCEnumValue` object. -- * \retval NULL -- * If not found. -- */ --PROTOBUF_C__API --const ProtobufCEnumValue * --protobuf_c_enum_descriptor_get_value( -- const ProtobufCEnumDescriptor *desc, -- int value); -- --/** -- * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by -- * the name of the field. -- * -- * \param desc -- * The `ProtobufCMessageDescriptor` object. -- * \param name -- * The name of the field. -- * \return -- * A `ProtobufCFieldDescriptor` object. -- * \retval NULL -- * If not found. -- */ --PROTOBUF_C__API --const ProtobufCFieldDescriptor * --protobuf_c_message_descriptor_get_field_by_name( -- const ProtobufCMessageDescriptor *desc, -- const char *name); -- --/** -- * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by -- * the tag value of the field. -- * -- * \param desc -- * The `ProtobufCMessageDescriptor` object. -- * \param value -- * The tag value of the field. -- * \return -- * A `ProtobufCFieldDescriptor` object. -- * \retval NULL -- * If not found. -- */ --PROTOBUF_C__API --const ProtobufCFieldDescriptor * --protobuf_c_message_descriptor_get_field( -- const ProtobufCMessageDescriptor *desc, -- unsigned value); -- --/** -- * Determine the number of bytes required to store the serialised message. -- * -- * \param message -- * The message object to serialise. -- * \return -- * Number of bytes. -- */ --PROTOBUF_C__API --size_t --protobuf_c_message_get_packed_size(const ProtobufCMessage *message); -- --/** -- * Serialise a message from its in-memory representation. -- * -- * This function stores the serialised bytes of the message in a pre-allocated -- * buffer. -- * -- * \param message -- * The message object to serialise. -- * \param[out] out -- * Buffer to store the bytes of the serialised message. This buffer must -- * have enough space to store the packed message. Use -- * protobuf_c_message_get_packed_size() to determine the number of bytes -- * required. -- * \return -- * Number of bytes stored in `out`. -- */ --PROTOBUF_C__API --size_t --protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out); -- --/** -- * Serialise a message from its in-memory representation to a virtual buffer. -- * -- * This function calls the `append` method of a `ProtobufCBuffer` object to -- * consume the bytes generated by the serialiser. -- * -- * \param message -- * The message object to serialise. -- * \param buffer -- * The virtual buffer object. -- * \return -- * Number of bytes passed to the virtual buffer. -- */ --PROTOBUF_C__API --size_t --protobuf_c_message_pack_to_buffer( -- const ProtobufCMessage *message, -- ProtobufCBuffer *buffer); -- --/** -- * Unpack a serialised message into an in-memory representation. -- * -- * \param descriptor -- * The message descriptor. -- * \param allocator -- * `ProtobufCAllocator` to use for memory allocation. May be NULL to -- * specify the default allocator. -- * \param len -- * Length in bytes of the serialised message. -- * \param data -- * Pointer to the serialised message. -- * \return -- * An unpacked message object. -- * \retval NULL -- * If an error occurred during unpacking. -- */ --PROTOBUF_C__API --ProtobufCMessage * --protobuf_c_message_unpack( -- const ProtobufCMessageDescriptor *descriptor, -- ProtobufCAllocator *allocator, -- size_t len, -- const uint8_t *data); -- --/** -- * Free an unpacked message object. -- * -- * This function should be used to deallocate the memory used by a call to -- * protobuf_c_message_unpack(). -- * -- * \param message -- * The message object to free. -- * \param allocator -- * `ProtobufCAllocator` to use for memory deallocation. May be NULL to -- * specify the default allocator. -- */ --PROTOBUF_C__API --void --protobuf_c_message_free_unpacked( -- ProtobufCMessage *message, -- ProtobufCAllocator *allocator); -- --/** -- * Check the validity of a message object. -- * -- * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present. -- * Recursively checks nested messages. -- * -- * \retval TRUE -- * Message is valid. -- * \retval FALSE -- * Message is invalid. -- */ --PROTOBUF_C__API --protobuf_c_boolean --protobuf_c_message_check(const ProtobufCMessage *); -- --/** Message initialiser. */ --#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL } -- --/** -- * Initialise a message object from a message descriptor. -- * -- * \param descriptor -- * Message descriptor. -- * \param message -- * Allocated block of memory of size `descriptor->sizeof_message`. -- */ --PROTOBUF_C__API --void --protobuf_c_message_init( -- const ProtobufCMessageDescriptor *descriptor, -- void *message); -- --/** -- * Free a service. -- * -- * \param service -- * The service object to free. -- */ --PROTOBUF_C__API --void --protobuf_c_service_destroy(ProtobufCService *service); -- --/** -- * Look up a `ProtobufCMethodDescriptor` by name. -- * -- * \param desc -- * Service descriptor. -- * \param name -- * Name of the method. -- * -- * \return -- * A `ProtobufCMethodDescriptor` object. -- * \retval NULL -- * If not found. -- */ --PROTOBUF_C__API --const ProtobufCMethodDescriptor * --protobuf_c_service_descriptor_get_method_by_name( -- const ProtobufCServiceDescriptor *desc, -- const char *name); -- --/** -- * Initialise a `ProtobufCBufferSimple` object. -- */ --#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \ --{ \ -- { protobuf_c_buffer_simple_append }, \ -- sizeof(array_of_bytes), \ -- 0, \ -- (array_of_bytes), \ -- 0, \ -- NULL \ --} -- --/** -- * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory. -- */ --#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \ --do { \ -- if ((simp_buf)->must_free_data) { \ -- if ((simp_buf)->allocator != NULL) \ -- (simp_buf)->allocator->free( \ -- (simp_buf)->allocator, \ -- (simp_buf)->data); \ -- else \ -- free((simp_buf)->data); \ -- } \ --} while (0) -- --/** -- * The `append` method for `ProtobufCBufferSimple`. -- * -- * \param buffer -- * The buffer object to append to. Must actually be a -- * `ProtobufCBufferSimple` object. -- * \param len -- * Number of bytes in `data`. -- * \param data -- * Data to append. -- */ --PROTOBUF_C__API --void --protobuf_c_buffer_simple_append( -- ProtobufCBuffer *buffer, -- size_t len, -- const unsigned char *data); -- --PROTOBUF_C__API --void --protobuf_c_service_generated_init( -- ProtobufCService *service, -- const ProtobufCServiceDescriptor *descriptor, -- ProtobufCServiceDestroy destroy); -- --PROTOBUF_C__API --void --protobuf_c_service_invoke_internal( -- ProtobufCService *service, -- unsigned method_index, -- const ProtobufCMessage *input, -- ProtobufCClosure closure, -- void *closure_data); -- --/**@}*/ -- --PROTOBUF_C__END_DECLS -- --#endif /* PROTOBUF_C_H */ -diff --git a/src/protobuf/protobuf-c/protobuf-c.c b/src/protobuf/protobuf-c/protobuf-c.c -new file mode 100644 -index 0000000..c7fb21d ---- /dev/null -+++ b/src/protobuf/protobuf-c/protobuf-c.c -@@ -0,0 +1,3272 @@ -+/* -+ * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are -+ * met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * * Redistributions in binary form must reproduce the above -+ * copyright notice, this list of conditions and the following disclaimer -+ * in the documentation and/or other materials provided with the -+ * distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/*! \file -+ * Support library for `protoc-c` generated code. -+ * -+ * This file implements the public API used by the code generated -+ * by `protoc-c`. -+ * -+ * \authors Dave Benson and the protobuf-c authors -+ * -+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. -+ */ -+ -+/** -+ * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math -+ * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64). -+ * -+ * \todo Use size_t consistently. -+ */ -+ -+#include /* for malloc, free */ -+#include /* for strcmp, strlen, memcpy, memmove, memset */ -+ -+#include "protobuf-c.h" -+ -+#define TRUE 1 -+#define FALSE 0 -+ -+#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0) -+ -+/** -+ * \defgroup internal Internal functions and macros -+ * -+ * These are not exported by the library but are useful to developers working -+ * on `libprotobuf-c` itself. -+ */ -+ -+/** -+ * \defgroup macros Utility macros for manipulating structures -+ * -+ * Macros and constants used to manipulate the base "classes" generated by -+ * `protobuf-c`. They also define limits and check correctness. -+ * -+ * \ingroup internal -+ * @{ -+ */ -+ -+/** The maximum length of a 64-bit integer in varint encoding. */ -+#define MAX_UINT64_ENCODED_SIZE 10 -+ -+#ifndef PROTOBUF_C_UNPACK_ERROR -+# define PROTOBUF_C_UNPACK_ERROR(...) -+#endif -+ -+/** -+ * Internal `ProtobufCMessage` manipulation macro. -+ * -+ * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and -+ * STRUCT_MEMBER_PTR(). -+ */ -+#define STRUCT_MEMBER_P(struct_p, struct_offset) \ -+ ((void *) ((uint8_t *) (struct_p) + (struct_offset))) -+ -+/** -+ * Return field in a `ProtobufCMessage` based on offset. -+ * -+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset. -+ * Cast it to the passed type. -+ */ -+#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ -+ (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) -+ -+/** -+ * Return field in a `ProtobufCMessage` based on offset. -+ * -+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast -+ * it to a pointer to the passed type. -+ */ -+#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ -+ ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset))) -+ -+/* Assertions for magic numbers. */ -+ -+#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \ -+ assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC) -+ -+#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \ -+ assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) -+ -+#define ASSERT_IS_MESSAGE(message) \ -+ ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor) -+ -+#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \ -+ assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC) -+ -+/**@}*/ -+ -+/* --- version --- */ -+ -+const char * -+protobuf_c_version(void) -+{ -+ return PROTOBUF_C_VERSION; -+} -+ -+uint32_t -+protobuf_c_version_number(void) -+{ -+ return PROTOBUF_C_VERSION_NUMBER; -+} -+ -+/* --- allocator --- */ -+ -+static void * -+system_alloc(void *allocator_data, size_t size) -+{ -+ return malloc(size); -+} -+ -+static void -+system_free(void *allocator_data, void *data) -+{ -+ free(data); -+} -+ -+static inline void * -+do_alloc(ProtobufCAllocator *allocator, size_t size) -+{ -+ return allocator->alloc(allocator->allocator_data, size); -+} -+ -+static inline void -+do_free(ProtobufCAllocator *allocator, void *data) -+{ -+ if (data != NULL) -+ allocator->free(allocator->allocator_data, data); -+} -+ -+/* -+ * This allocator uses the system's malloc() and free(). It is the default -+ * allocator used if NULL is passed as the ProtobufCAllocator to an exported -+ * function. -+ */ -+static ProtobufCAllocator protobuf_c__allocator = { -+ .alloc = &system_alloc, -+ .free = &system_free, -+ .allocator_data = NULL, -+}; -+ -+/* === buffer-simple === */ -+ -+void -+protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer, -+ size_t len, const uint8_t *data) -+{ -+ ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; -+ size_t new_len = simp->len + len; -+ -+ if (new_len > simp->alloced) { -+ ProtobufCAllocator *allocator = simp->allocator; -+ size_t new_alloced = simp->alloced * 2; -+ uint8_t *new_data; -+ -+ if (allocator == NULL) -+ allocator = &protobuf_c__allocator; -+ while (new_alloced < new_len) -+ new_alloced += new_alloced; -+ new_data = do_alloc(allocator, new_alloced); -+ if (!new_data) -+ return; -+ memcpy(new_data, simp->data, simp->len); -+ if (simp->must_free_data) -+ do_free(allocator, simp->data); -+ else -+ simp->must_free_data = TRUE; -+ simp->data = new_data; -+ simp->alloced = new_alloced; -+ } -+ memcpy(simp->data + simp->len, data, len); -+ simp->len = new_len; -+} -+ -+/** -+ * \defgroup packedsz protobuf_c_message_get_packed_size() implementation -+ * -+ * Routines mainly used by protobuf_c_message_get_packed_size(). -+ * -+ * \ingroup internal -+ * @{ -+ */ -+ -+/** -+ * Return the number of bytes required to store the tag for the field. Includes -+ * 3 bits for the wire-type, and a single bit that denotes the end-of-tag. -+ * -+ * \param number -+ * Field tag to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+get_tag_size(unsigned number) -+{ -+ if (number < (1 << 4)) { -+ return 1; -+ } else if (number < (1 << 11)) { -+ return 2; -+ } else if (number < (1 << 18)) { -+ return 3; -+ } else if (number < (1 << 25)) { -+ return 4; -+ } else { -+ return 5; -+ } -+} -+ -+/** -+ * Return the number of bytes required to store a variable-length unsigned -+ * 32-bit integer in base-128 varint encoding. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+uint32_size(uint32_t v) -+{ -+ if (v < (1 << 7)) { -+ return 1; -+ } else if (v < (1 << 14)) { -+ return 2; -+ } else if (v < (1 << 21)) { -+ return 3; -+ } else if (v < (1 << 28)) { -+ return 4; -+ } else { -+ return 5; -+ } -+} -+ -+/** -+ * Return the number of bytes required to store a variable-length signed 32-bit -+ * integer in base-128 varint encoding. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+int32_size(int32_t v) -+{ -+ if (v < 0) { -+ return 10; -+ } else if (v < (1 << 7)) { -+ return 1; -+ } else if (v < (1 << 14)) { -+ return 2; -+ } else if (v < (1 << 21)) { -+ return 3; -+ } else if (v < (1 << 28)) { -+ return 4; -+ } else { -+ return 5; -+ } -+} -+ -+/** -+ * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed -+ * integer. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * ZigZag encoded integer. -+ */ -+static inline uint32_t -+zigzag32(int32_t v) -+{ -+ if (v < 0) -+ return ((uint32_t) (-v)) * 2 - 1; -+ else -+ return v * 2; -+} -+ -+/** -+ * Return the number of bytes required to store a signed 32-bit integer, -+ * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128 -+ * varint encoding. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+sint32_size(int32_t v) -+{ -+ return uint32_size(zigzag32(v)); -+} -+ -+/** -+ * Return the number of bytes required to store a 64-bit unsigned integer in -+ * base-128 varint encoding. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+uint64_size(uint64_t v) -+{ -+ uint32_t upper_v = (uint32_t) (v >> 32); -+ -+ if (upper_v == 0) { -+ return uint32_size((uint32_t) v); -+ } else if (upper_v < (1 << 3)) { -+ return 5; -+ } else if (upper_v < (1 << 10)) { -+ return 6; -+ } else if (upper_v < (1 << 17)) { -+ return 7; -+ } else if (upper_v < (1 << 24)) { -+ return 8; -+ } else if (upper_v < (1U << 31)) { -+ return 9; -+ } else { -+ return 10; -+ } -+} -+ -+/** -+ * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed -+ * integer. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * ZigZag encoded integer. -+ */ -+static inline uint64_t -+zigzag64(int64_t v) -+{ -+ if (v < 0) -+ return ((uint64_t) (-v)) * 2 - 1; -+ else -+ return v * 2; -+} -+ -+/** -+ * Return the number of bytes required to store a signed 64-bit integer, -+ * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128 -+ * varint encoding. -+ * -+ * \param v -+ * Value to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+sint64_size(int64_t v) -+{ -+ return uint64_size(zigzag64(v)); -+} -+ -+/** -+ * Calculate the serialized size of a single required message field, including -+ * the space needed by the preceding tag. -+ * -+ * \param field -+ * Field descriptor for member. -+ * \param member -+ * Field to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static size_t -+required_field_get_packed_size(const ProtobufCFieldDescriptor *field, -+ const void *member) -+{ -+ size_t rv = get_tag_size(field->id); -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SINT32: -+ return rv + sint32_size(*(const int32_t *) member); -+ case PROTOBUF_C_TYPE_INT32: -+ return rv + int32_size(*(const uint32_t *) member); -+ case PROTOBUF_C_TYPE_UINT32: -+ return rv + uint32_size(*(const uint32_t *) member); -+ case PROTOBUF_C_TYPE_SINT64: -+ return rv + sint64_size(*(const int64_t *) member); -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ return rv + uint64_size(*(const uint64_t *) member); -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ return rv + 4; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ return rv + 8; -+ case PROTOBUF_C_TYPE_BOOL: -+ return rv + 1; -+ case PROTOBUF_C_TYPE_FLOAT: -+ return rv + 4; -+ case PROTOBUF_C_TYPE_DOUBLE: -+ return rv + 8; -+ case PROTOBUF_C_TYPE_ENUM: -+ /* \todo Is this correct for negative-valued enums? */ -+ return rv + uint32_size(*(const uint32_t *) member); -+ case PROTOBUF_C_TYPE_STRING: { -+ const char *str = *(char * const *) member; -+ size_t len = str ? strlen(str) : 0; -+ return rv + uint32_size(len) + len; -+ } -+ case PROTOBUF_C_TYPE_BYTES: { -+ size_t len = ((const ProtobufCBinaryData *) member)->len; -+ return rv + uint32_size(len) + len; -+ } -+ case PROTOBUF_C_TYPE_MESSAGE: { -+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; -+ size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0; -+ return rv + uint32_size(subrv) + subrv; -+ } -+ } -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ return 0; -+} -+ -+/** -+ * Calculate the serialized size of a single optional message field, including -+ * the space needed by the preceding tag. Returns 0 if the optional field isn't -+ * set. -+ * -+ * \param field -+ * Field descriptor for member. -+ * \param has -+ * True if the field exists, false if not. -+ * \param member -+ * Field to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static size_t -+optional_field_get_packed_size(const ProtobufCFieldDescriptor *field, -+ const protobuf_c_boolean *has, -+ const void *member) -+{ -+ if (field->type == PROTOBUF_C_TYPE_MESSAGE || -+ field->type == PROTOBUF_C_TYPE_STRING) -+ { -+ const void *ptr = *(const void * const *) member; -+ if (ptr == NULL || ptr == field->default_value) -+ return 0; -+ } else { -+ if (!*has) -+ return 0; -+ } -+ return required_field_get_packed_size(field, member); -+} -+ -+/** -+ * Calculate the serialized size of repeated message fields, which may consist -+ * of any number of values (including 0). Includes the space needed by the -+ * preceding tags (as needed). -+ * -+ * \param field -+ * Field descriptor for member. -+ * \param count -+ * Number of repeated field members. -+ * \param member -+ * Field to encode. -+ * \return -+ * Number of bytes required. -+ */ -+static size_t -+repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field, -+ size_t count, const void *member) -+{ -+ size_t header_size; -+ size_t rv = 0; -+ unsigned i; -+ void *array = *(void * const *) member; -+ -+ if (count == 0) -+ return 0; -+ header_size = get_tag_size(field->id); -+ if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) -+ header_size *= count; -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SINT32: -+ for (i = 0; i < count; i++) -+ rv += sint32_size(((int32_t *) array)[i]); -+ break; -+ case PROTOBUF_C_TYPE_INT32: -+ for (i = 0; i < count; i++) -+ rv += int32_size(((uint32_t *) array)[i]); -+ break; -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_ENUM: -+ for (i = 0; i < count; i++) -+ rv += uint32_size(((uint32_t *) array)[i]); -+ break; -+ case PROTOBUF_C_TYPE_SINT64: -+ for (i = 0; i < count; i++) -+ rv += sint64_size(((int64_t *) array)[i]); -+ break; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ for (i = 0; i < count; i++) -+ rv += uint64_size(((uint64_t *) array)[i]); -+ break; -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ rv += 4 * count; -+ break; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ rv += 8 * count; -+ break; -+ case PROTOBUF_C_TYPE_BOOL: -+ rv += count; -+ break; -+ case PROTOBUF_C_TYPE_STRING: -+ for (i = 0; i < count; i++) { -+ size_t len = strlen(((char **) array)[i]); -+ rv += uint32_size(len) + len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_BYTES: -+ for (i = 0; i < count; i++) { -+ size_t len = ((ProtobufCBinaryData *) array)[i].len; -+ rv += uint32_size(len) + len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_MESSAGE: -+ for (i = 0; i < count; i++) { -+ size_t len = protobuf_c_message_get_packed_size( -+ ((ProtobufCMessage **) array)[i]); -+ rv += uint32_size(len) + len; -+ } -+ break; -+ } -+ -+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) -+ header_size += uint32_size(rv); -+ return header_size + rv; -+} -+ -+/** -+ * Calculate the serialized size of an unknown field, i.e. one that is passed -+ * through mostly uninterpreted. This is required for forward compatibility if -+ * new fields are added to the message descriptor. -+ * -+ * \param field -+ * Unknown field type. -+ * \return -+ * Number of bytes required. -+ */ -+static inline size_t -+unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field) -+{ -+ return get_tag_size(field->tag) + field->len; -+} -+ -+/**@}*/ -+ -+/* -+ * Calculate the serialized size of the message. -+ */ -+size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) -+{ -+ unsigned i; -+ size_t rv = 0; -+ -+ ASSERT_IS_MESSAGE(message); -+ for (i = 0; i < message->descriptor->n_fields; i++) { -+ const ProtobufCFieldDescriptor *field = -+ message->descriptor->fields + i; -+ const void *member = -+ ((const char *) message) + field->offset; -+ const void *qmember = -+ ((const char *) message) + field->quantifier_offset; -+ -+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -+ rv += required_field_get_packed_size(field, member); -+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -+ rv += optional_field_get_packed_size(field, qmember, member); -+ } else { -+ rv += repeated_field_get_packed_size( -+ field, -+ *(const size_t *) qmember, -+ member -+ ); -+ } -+ } -+ for (i = 0; i < message->n_unknown_fields; i++) -+ rv += unknown_field_get_packed_size(&message->unknown_fields[i]); -+ return rv; -+} -+ -+/** -+ * \defgroup pack protobuf_c_message_pack() implementation -+ * -+ * Routines mainly used by protobuf_c_message_pack(). -+ * -+ * \ingroup internal -+ * @{ -+ */ -+ -+/** -+ * Pack an unsigned 32-bit integer in base-128 varint encoding and return the -+ * number of bytes written, which must be 5 or less. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+uint32_pack(uint32_t value, uint8_t *out) -+{ -+ unsigned rv = 0; -+ -+ if (value >= 0x80) { -+ out[rv++] = value | 0x80; -+ value >>= 7; -+ if (value >= 0x80) { -+ out[rv++] = value | 0x80; -+ value >>= 7; -+ if (value >= 0x80) { -+ out[rv++] = value | 0x80; -+ value >>= 7; -+ if (value >= 0x80) { -+ out[rv++] = value | 0x80; -+ value >>= 7; -+ } -+ } -+ } -+ } -+ /* assert: value<128 */ -+ out[rv++] = value; -+ return rv; -+} -+ -+/** -+ * Pack a signed 32-bit integer and return the number of bytes written. -+ * Negative numbers are encoded as two's complement 64-bit integers. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+int32_pack(int32_t value, uint8_t *out) -+{ -+ if (value < 0) { -+ out[0] = value | 0x80; -+ out[1] = (value >> 7) | 0x80; -+ out[2] = (value >> 14) | 0x80; -+ out[3] = (value >> 21) | 0x80; -+ out[4] = (value >> 28) | 0x80; -+ out[5] = out[6] = out[7] = out[8] = 0xff; -+ out[9] = 0x01; -+ return 10; -+ } else { -+ return uint32_pack(value, out); -+ } -+} -+ -+/** -+ * Pack a signed 32-bit integer using ZigZag encoding and return the number of -+ * bytes written. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+sint32_pack(int32_t value, uint8_t *out) -+{ -+ return uint32_pack(zigzag32(value), out); -+} -+ -+/** -+ * Pack a 64-bit unsigned integer using base-128 varint encoding and return the -+ * number of bytes written. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static size_t -+uint64_pack(uint64_t value, uint8_t *out) -+{ -+ uint32_t hi = (uint32_t) (value >> 32); -+ uint32_t lo = (uint32_t) value; -+ unsigned rv; -+ -+ if (hi == 0) -+ return uint32_pack((uint32_t) lo, out); -+ out[0] = (lo) | 0x80; -+ out[1] = (lo >> 7) | 0x80; -+ out[2] = (lo >> 14) | 0x80; -+ out[3] = (lo >> 21) | 0x80; -+ if (hi < 8) { -+ out[4] = (hi << 4) | (lo >> 28); -+ return 5; -+ } else { -+ out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80; -+ hi >>= 3; -+ } -+ rv = 5; -+ while (hi >= 128) { -+ out[rv++] = hi | 0x80; -+ hi >>= 7; -+ } -+ out[rv++] = hi; -+ return rv; -+} -+ -+/** -+ * Pack a 64-bit signed integer in ZigZag encoding and return the number of -+ * bytes written. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+sint64_pack(int64_t value, uint8_t *out) -+{ -+ return uint64_pack(zigzag64(value), out); -+} -+ -+/** -+ * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire -+ * types fixed32, sfixed32, float. Similar to "htole32". -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+fixed32_pack(uint32_t value, void *out) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ memcpy(out, &value, 4); -+#else -+ uint8_t *buf = out; -+ -+ buf[0] = value; -+ buf[1] = value >> 8; -+ buf[2] = value >> 16; -+ buf[3] = value >> 24; -+#endif -+ return 4; -+} -+ -+/** -+ * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire -+ * types fixed64, sfixed64, double. Similar to "htole64". -+ * -+ * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit -+ * version would be appreciated, plus a way to decide to use 64-bit math where -+ * convenient. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+fixed64_pack(uint64_t value, void *out) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ memcpy(out, &value, 8); -+#else -+ fixed32_pack(value, out); -+ fixed32_pack(value >> 32, ((char *) out) + 4); -+#endif -+ return 8; -+} -+ -+/** -+ * Pack a boolean value as an integer and return the number of bytes written. -+ * -+ * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c -+ * that is idiomatic C++ in some STL implementations. -+ * -+ * \param value -+ * Value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+boolean_pack(protobuf_c_boolean value, uint8_t *out) -+{ -+ *out = value ? TRUE : FALSE; -+ return 1; -+} -+ -+/** -+ * Pack a NUL-terminated C string and return the number of bytes written. The -+ * output includes a length delimiter. -+ * -+ * The NULL pointer is treated as an empty string. This isn't really necessary, -+ * but it allows people to leave required strings blank. (See Issue #13 in the -+ * bug tracker for a little more explanation). -+ * -+ * \param str -+ * String to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+string_pack(const char *str, uint8_t *out) -+{ -+ if (str == NULL) { -+ out[0] = 0; -+ return 1; -+ } else { -+ size_t len = strlen(str); -+ size_t rv = uint32_pack(len, out); -+ memcpy(out + rv, str, len); -+ return rv + len; -+ } -+} -+ -+/** -+ * Pack a ProtobufCBinaryData and return the number of bytes written. The output -+ * includes a length delimiter. -+ * -+ * \param bd -+ * ProtobufCBinaryData to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out) -+{ -+ size_t len = bd->len; -+ size_t rv = uint32_pack(len, out); -+ memcpy(out + rv, bd->data, len); -+ return rv + len; -+} -+ -+/** -+ * Pack a ProtobufCMessage and return the number of bytes written. The output -+ * includes a length delimiter. -+ * -+ * \param message -+ * ProtobufCMessage object to pack. -+ * \param[out] out -+ * Packed message. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static inline size_t -+prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out) -+{ -+ if (message == NULL) { -+ out[0] = 0; -+ return 1; -+ } else { -+ size_t rv = protobuf_c_message_pack(message, out + 1); -+ uint32_t rv_packed_size = uint32_size(rv); -+ if (rv_packed_size != 1) -+ memmove(out + rv_packed_size, out + 1, rv); -+ return uint32_pack(rv, out) + rv; -+ } -+} -+ -+/** -+ * Pack a field tag. -+ * -+ * Wire-type will be added in required_field_pack(). -+ * -+ * \todo Just call uint64_pack on 64-bit platforms. -+ * -+ * \param id -+ * Tag value to encode. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static size_t -+tag_pack(uint32_t id, uint8_t *out) -+{ -+ if (id < (1 << (32 - 3))) -+ return uint32_pack(id << 3, out); -+ else -+ return uint64_pack(((uint64_t) id) << 3, out); -+} -+ -+/** -+ * Pack a required field and return the number of bytes written. -+ * -+ * \param field -+ * Field descriptor. -+ * \param member -+ * The field member. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static size_t -+required_field_pack(const ProtobufCFieldDescriptor *field, -+ const void *member, uint8_t *out) -+{ -+ size_t rv = tag_pack(field->id, out); -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SINT32: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + sint32_pack(*(const int32_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_INT32: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + int32_pack(*(const uint32_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_ENUM: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + uint32_pack(*(const uint32_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_SINT64: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + sint64_pack(*(const int64_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + uint64_pack(*(const uint64_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; -+ return rv + fixed32_pack(*(const uint32_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; -+ return rv + fixed64_pack(*(const uint64_t *) member, out + rv); -+ case PROTOBUF_C_TYPE_BOOL: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv); -+ case PROTOBUF_C_TYPE_STRING: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ return rv + string_pack(*(char *const *) member, out + rv); -+ case PROTOBUF_C_TYPE_BYTES: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv); -+ case PROTOBUF_C_TYPE_MESSAGE: -+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv); -+ } -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ return 0; -+} -+ -+/** -+ * Pack an optional field and return the number of bytes written. -+ * -+ * \param field -+ * Field descriptor. -+ * \param has -+ * Whether the field is set. -+ * \param member -+ * The field member. -+ * \param[out] out -+ * Packed value. -+ * \return -+ * Number of bytes written to `out`. -+ */ -+static size_t -+optional_field_pack(const ProtobufCFieldDescriptor *field, -+ const protobuf_c_boolean *has, -+ const void *member, uint8_t *out) -+{ -+ if (field->type == PROTOBUF_C_TYPE_MESSAGE || -+ field->type == PROTOBUF_C_TYPE_STRING) -+ { -+ const void *ptr = *(const void * const *) member; -+ if (ptr == NULL || ptr == field->default_value) -+ return 0; -+ } else { -+ if (!*has) -+ return 0; -+ } -+ return required_field_pack(field, member, out); -+} -+ -+/** -+ * Given a field type, return the in-memory size. -+ * -+ * \todo Implement as a table lookup. -+ * -+ * \param type -+ * Field type. -+ * \return -+ * Size of the field. -+ */ -+static inline size_t -+sizeof_elt_in_repeated_array(ProtobufCType type) -+{ -+ switch (type) { -+ case PROTOBUF_C_TYPE_SINT32: -+ case PROTOBUF_C_TYPE_INT32: -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ case PROTOBUF_C_TYPE_ENUM: -+ return 4; -+ case PROTOBUF_C_TYPE_SINT64: -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ return 8; -+ case PROTOBUF_C_TYPE_BOOL: -+ return sizeof(protobuf_c_boolean); -+ case PROTOBUF_C_TYPE_STRING: -+ case PROTOBUF_C_TYPE_MESSAGE: -+ return sizeof(void *); -+ case PROTOBUF_C_TYPE_BYTES: -+ return sizeof(ProtobufCBinaryData); -+ } -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ return 0; -+} -+ -+/** -+ * Pack an array of 32-bit quantities. -+ * -+ * \param[out] out -+ * Destination. -+ * \param[in] in -+ * Source. -+ * \param[in] n -+ * Number of elements in the source array. -+ */ -+static void -+copy_to_little_endian_32(void *out, const void *in, const unsigned n) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ memcpy(out, in, n * 4); -+#else -+ unsigned i; -+ const uint32_t *ini = in; -+ for (i = 0; i < n; i++) -+ fixed32_pack(ini[i], (uint32_t *) out + i); -+#endif -+} -+ -+/** -+ * Pack an array of 64-bit quantities. -+ * -+ * \param[out] out -+ * Destination. -+ * \param[in] in -+ * Source. -+ * \param[in] n -+ * Number of elements in the source array. -+ */ -+static void -+copy_to_little_endian_64(void *out, const void *in, const unsigned n) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ memcpy(out, in, n * 8); -+#else -+ unsigned i; -+ const uint64_t *ini = in; -+ for (i = 0; i < n; i++) -+ fixed64_pack(ini[i], (uint64_t *) out + i); -+#endif -+} -+ -+/** -+ * Get the minimum number of bytes required to pack a field value of a -+ * particular type. -+ * -+ * \param type -+ * Field type. -+ * \return -+ * Number of bytes. -+ */ -+static unsigned -+get_type_min_size(ProtobufCType type) -+{ -+ if (type == PROTOBUF_C_TYPE_SFIXED32 || -+ type == PROTOBUF_C_TYPE_FIXED32 || -+ type == PROTOBUF_C_TYPE_FLOAT) -+ { -+ return 4; -+ } -+ if (type == PROTOBUF_C_TYPE_SFIXED64 || -+ type == PROTOBUF_C_TYPE_FIXED64 || -+ type == PROTOBUF_C_TYPE_DOUBLE) -+ { -+ return 8; -+ } -+ return 1; -+} -+ -+/** -+ * Packs the elements of a repeated field and returns the serialised field and -+ * its length. -+ * -+ * \param field -+ * Field descriptor. -+ * \param count -+ * Number of elements in the repeated field array. -+ * \param member -+ * Pointer to the elements for this repeated field. -+ * \param[out] out -+ * Serialised representation of the repeated field. -+ * \return -+ * Number of bytes serialised to `out`. -+ */ -+static size_t -+repeated_field_pack(const ProtobufCFieldDescriptor *field, -+ size_t count, const void *member, uint8_t *out) -+{ -+ void *array = *(void * const *) member; -+ unsigned i; -+ -+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { -+ unsigned header_len; -+ unsigned len_start; -+ unsigned min_length; -+ unsigned payload_len; -+ unsigned length_size_min; -+ unsigned actual_length_size; -+ uint8_t *payload_at; -+ -+ if (count == 0) -+ return 0; -+ header_len = tag_pack(field->id, out); -+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ len_start = header_len; -+ min_length = get_type_min_size(field->type) * count; -+ length_size_min = uint32_size(min_length); -+ header_len += length_size_min; -+ payload_at = out + header_len; -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ copy_to_little_endian_32(payload_at, array, count); -+ payload_at += count * 4; -+ break; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ copy_to_little_endian_64(payload_at, array, count); -+ payload_at += count * 8; -+ break; -+ case PROTOBUF_C_TYPE_INT32: { -+ const int32_t *arr = (const int32_t *) array; -+ for (i = 0; i < count; i++) -+ payload_at += int32_pack(arr[i], payload_at); -+ break; -+ } -+ case PROTOBUF_C_TYPE_SINT32: { -+ const int32_t *arr = (const int32_t *) array; -+ for (i = 0; i < count; i++) -+ payload_at += sint32_pack(arr[i], payload_at); -+ break; -+ } -+ case PROTOBUF_C_TYPE_SINT64: { -+ const int64_t *arr = (const int64_t *) array; -+ for (i = 0; i < count; i++) -+ payload_at += sint64_pack(arr[i], payload_at); -+ break; -+ } -+ case PROTOBUF_C_TYPE_ENUM: -+ case PROTOBUF_C_TYPE_UINT32: { -+ const uint32_t *arr = (const uint32_t *) array; -+ for (i = 0; i < count; i++) -+ payload_at += uint32_pack(arr[i], payload_at); -+ break; -+ } -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: { -+ const uint64_t *arr = (const uint64_t *) array; -+ for (i = 0; i < count; i++) -+ payload_at += uint64_pack(arr[i], payload_at); -+ break; -+ } -+ case PROTOBUF_C_TYPE_BOOL: { -+ const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array; -+ for (i = 0; i < count; i++) -+ payload_at += boolean_pack(arr[i], payload_at); -+ break; -+ } -+ default: -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ } -+ -+ payload_len = payload_at - (out + header_len); -+ actual_length_size = uint32_size(payload_len); -+ if (length_size_min != actual_length_size) { -+ assert(actual_length_size == length_size_min + 1); -+ memmove(out + header_len + 1, out + header_len, -+ payload_len); -+ header_len++; -+ } -+ uint32_pack(payload_len, out + len_start); -+ return header_len + payload_len; -+ } else { -+ /* not "packed" cased */ -+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ -+ size_t rv = 0; -+ unsigned siz = sizeof_elt_in_repeated_array(field->type); -+ -+ for (i = 0; i < count; i++) { -+ rv += required_field_pack(field, array, out + rv); -+ array = (char *)array + siz; -+ } -+ return rv; -+ } -+} -+ -+static size_t -+unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out) -+{ -+ size_t rv = tag_pack(field->tag, out); -+ out[0] |= field->wire_type; -+ memcpy(out + rv, field->data, field->len); -+ return rv + field->len; -+} -+ -+/**@}*/ -+ -+size_t -+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out) -+{ -+ unsigned i; -+ size_t rv = 0; -+ -+ ASSERT_IS_MESSAGE(message); -+ for (i = 0; i < message->descriptor->n_fields; i++) { -+ const ProtobufCFieldDescriptor *field = -+ message->descriptor->fields + i; -+ const void *member = ((const char *) message) + field->offset; -+ -+ /* -+ * It doesn't hurt to compute qmember (a pointer to the -+ * quantifier field of the structure), but the pointer is only -+ * valid if the field is: -+ * - a repeated field, or -+ * - an optional field that isn't a pointer type -+ * (Meaning: not a message or a string). -+ */ -+ const void *qmember = -+ ((const char *) message) + field->quantifier_offset; -+ -+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -+ rv += required_field_pack(field, member, out + rv); -+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -+ /* -+ * Note that qmember is bogus for strings and messages, -+ * but it isn't used. -+ */ -+ rv += optional_field_pack(field, qmember, member, out + rv); -+ } else { -+ rv += repeated_field_pack(field, *(const size_t *) qmember, -+ member, out + rv); -+ } -+ } -+ for (i = 0; i < message->n_unknown_fields; i++) -+ rv += unknown_field_pack(&message->unknown_fields[i], out + rv); -+ return rv; -+} -+ -+/** -+ * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation -+ * -+ * Routines mainly used by protobuf_c_message_pack_to_buffer(). -+ * -+ * \ingroup internal -+ * @{ -+ */ -+ -+/** -+ * Pack a required field to a virtual buffer. -+ * -+ * \param field -+ * Field descriptor. -+ * \param member -+ * The element to be packed. -+ * \param[out] buffer -+ * Virtual buffer to append data to. -+ * \return -+ * Number of bytes packed. -+ */ -+static size_t -+required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -+ const void *member, ProtobufCBuffer *buffer) -+{ -+ size_t rv; -+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; -+ -+ rv = tag_pack(field->id, scratch); -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SINT32: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += sint32_pack(*(const int32_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_INT32: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += int32_pack(*(const uint32_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_ENUM: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += uint32_pack(*(const uint32_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_SINT64: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += sint64_pack(*(const int64_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += uint64_pack(*(const uint64_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT; -+ rv += fixed32_pack(*(const uint32_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT; -+ rv += fixed64_pack(*(const uint64_t *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_BOOL: -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT; -+ rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ break; -+ case PROTOBUF_C_TYPE_STRING: { -+ const char *str = *(char *const *) member; -+ size_t sublen = str ? strlen(str) : 0; -+ -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ rv += uint32_pack(sublen, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ buffer->append(buffer, sublen, (const uint8_t *) str); -+ rv += sublen; -+ break; -+ } -+ case PROTOBUF_C_TYPE_BYTES: { -+ const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member); -+ size_t sublen = bd->len; -+ -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ rv += uint32_pack(sublen, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ buffer->append(buffer, sublen, bd->data); -+ rv += sublen; -+ break; -+ } -+ case PROTOBUF_C_TYPE_MESSAGE: { -+ uint8_t simple_buffer_scratch[256]; -+ size_t sublen; -+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member; -+ ProtobufCBufferSimple simple_buffer = -+ PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch); -+ -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ if (msg == NULL) -+ sublen = 0; -+ else -+ sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base); -+ rv += uint32_pack(sublen, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ buffer->append(buffer, sublen, simple_buffer.data); -+ rv += sublen; -+ PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer); -+ break; -+ } -+ default: -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ } -+ return rv; -+} -+ -+/** -+ * Pack an optional field to a buffer. -+ * -+ * \param field -+ * Field descriptor. -+ * \param has -+ * Whether the field is set. -+ * \param member -+ * The element to be packed. -+ * \param[out] buffer -+ * Virtual buffer to append data to. -+ * \return -+ * Number of bytes serialised to `buffer`. -+ */ -+static size_t -+optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -+ const protobuf_c_boolean *has, -+ const void *member, ProtobufCBuffer *buffer) -+{ -+ if (field->type == PROTOBUF_C_TYPE_MESSAGE || -+ field->type == PROTOBUF_C_TYPE_STRING) -+ { -+ const void *ptr = *(const void *const *) member; -+ if (ptr == NULL || ptr == field->default_value) -+ return 0; -+ } else { -+ if (!*has) -+ return 0; -+ } -+ return required_field_pack_to_buffer(field, member, buffer); -+} -+ -+/** -+ * Get the packed size of an array of same field type. -+ * -+ * \param field -+ * Field descriptor. -+ * \param count -+ * Number of elements of this type. -+ * \param array -+ * The elements to get the size of. -+ * \return -+ * Number of bytes required. -+ */ -+static size_t -+get_packed_payload_length(const ProtobufCFieldDescriptor *field, -+ unsigned count, const void *array) -+{ -+ unsigned rv = 0; -+ unsigned i; -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ return count * 4; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ return count * 8; -+ case PROTOBUF_C_TYPE_INT32: { -+ const int32_t *arr = (const int32_t *) array; -+ for (i = 0; i < count; i++) -+ rv += int32_size(arr[i]); -+ break; -+ } -+ case PROTOBUF_C_TYPE_SINT32: { -+ const int32_t *arr = (const int32_t *) array; -+ for (i = 0; i < count; i++) -+ rv += sint32_size(arr[i]); -+ break; -+ } -+ case PROTOBUF_C_TYPE_ENUM: -+ case PROTOBUF_C_TYPE_UINT32: { -+ const uint32_t *arr = (const uint32_t *) array; -+ for (i = 0; i < count; i++) -+ rv += uint32_size(arr[i]); -+ break; -+ } -+ case PROTOBUF_C_TYPE_SINT64: { -+ const int64_t *arr = (const int64_t *) array; -+ for (i = 0; i < count; i++) -+ rv += sint64_size(arr[i]); -+ break; -+ } -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: { -+ const uint64_t *arr = (const uint64_t *) array; -+ for (i = 0; i < count; i++) -+ rv += uint64_size(arr[i]); -+ break; -+ } -+ case PROTOBUF_C_TYPE_BOOL: -+ return count; -+ default: -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ } -+ return rv; -+} -+ -+/** -+ * Pack an array of same field type to a virtual buffer. -+ * -+ * \param field -+ * Field descriptor. -+ * \param count -+ * Number of elements of this type. -+ * \param array -+ * The elements to get the size of. -+ * \param[out] buffer -+ * Virtual buffer to append data to. -+ * \return -+ * Number of bytes packed. -+ */ -+static size_t -+pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field, -+ unsigned count, const void *array, -+ ProtobufCBuffer *buffer) -+{ -+ uint8_t scratch[16]; -+ size_t rv = 0; -+ unsigned i; -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+#if !defined(WORDS_BIGENDIAN) -+ rv = count * 4; -+ goto no_packing_needed; -+#else -+ for (i = 0; i < count; i++) { -+ unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+#endif -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+#if !defined(WORDS_BIGENDIAN) -+ rv = count * 8; -+ goto no_packing_needed; -+#else -+ for (i = 0; i < count; i++) { -+ unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+#endif -+ case PROTOBUF_C_TYPE_INT32: -+ for (i = 0; i < count; i++) { -+ unsigned len = int32_pack(((int32_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_SINT32: -+ for (i = 0; i < count; i++) { -+ unsigned len = sint32_pack(((int32_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_ENUM: -+ case PROTOBUF_C_TYPE_UINT32: -+ for (i = 0; i < count; i++) { -+ unsigned len = uint32_pack(((uint32_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_SINT64: -+ for (i = 0; i < count; i++) { -+ unsigned len = sint64_pack(((int64_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ for (i = 0; i < count; i++) { -+ unsigned len = uint64_pack(((uint64_t *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ break; -+ case PROTOBUF_C_TYPE_BOOL: -+ for (i = 0; i < count; i++) { -+ unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch); -+ buffer->append(buffer, len, scratch); -+ rv += len; -+ } -+ return count; -+ default: -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ } -+ return rv; -+ -+no_packing_needed: -+ buffer->append(buffer, rv, array); -+ return rv; -+} -+ -+static size_t -+repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field, -+ unsigned count, const void *member, -+ ProtobufCBuffer *buffer) -+{ -+ char *array = *(char * const *) member; -+ -+ if (count == 0) -+ return 0; -+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) { -+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; -+ size_t rv = tag_pack(field->id, scratch); -+ size_t payload_len = get_packed_payload_length(field, count, array); -+ size_t tmp; -+ -+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; -+ rv += uint32_pack(payload_len, scratch + rv); -+ buffer->append(buffer, rv, scratch); -+ tmp = pack_buffer_packed_payload(field, count, array, buffer); -+ assert(tmp == payload_len); -+ return rv + payload_len; -+ } else { -+ size_t siz; -+ unsigned i; -+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */ -+ unsigned rv = 0; -+ -+ siz = sizeof_elt_in_repeated_array(field->type); -+ for (i = 0; i < count; i++) { -+ rv += required_field_pack_to_buffer(field, array, buffer); -+ array += siz; -+ } -+ return rv; -+ } -+} -+ -+static size_t -+unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field, -+ ProtobufCBuffer *buffer) -+{ -+ uint8_t header[MAX_UINT64_ENCODED_SIZE]; -+ size_t rv = tag_pack(field->tag, header); -+ -+ header[0] |= field->wire_type; -+ buffer->append(buffer, rv, header); -+ buffer->append(buffer, field->len, field->data); -+ return rv + field->len; -+} -+ -+/**@}*/ -+ -+size_t -+protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message, -+ ProtobufCBuffer *buffer) -+{ -+ unsigned i; -+ size_t rv = 0; -+ -+ ASSERT_IS_MESSAGE(message); -+ for (i = 0; i < message->descriptor->n_fields; i++) { -+ const ProtobufCFieldDescriptor *field = -+ message->descriptor->fields + i; -+ const void *member = -+ ((const char *) message) + field->offset; -+ const void *qmember = -+ ((const char *) message) + field->quantifier_offset; -+ -+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -+ rv += required_field_pack_to_buffer(field, member, buffer); -+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) { -+ rv += optional_field_pack_to_buffer( -+ field, -+ qmember, -+ member, -+ buffer -+ ); -+ } else { -+ rv += repeated_field_pack_to_buffer( -+ field, -+ *(const size_t *) qmember, -+ member, -+ buffer -+ ); -+ } -+ } -+ for (i = 0; i < message->n_unknown_fields; i++) -+ rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer); -+ -+ return rv; -+} -+ -+/** -+ * \defgroup unpack unpacking implementation -+ * -+ * Routines mainly used by the unpacking functions. -+ * -+ * \ingroup internal -+ * @{ -+ */ -+ -+static inline int -+int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value) -+{ -+ unsigned n; -+ unsigned start; -+ -+ if (n_ranges == 0) -+ return -1; -+ start = 0; -+ n = n_ranges; -+ while (n > 1) { -+ unsigned mid = start + n / 2; -+ -+ if (value < ranges[mid].start_value) { -+ n = mid - start; -+ } else if (value >= ranges[mid].start_value + -+ (int) (ranges[mid + 1].orig_index - -+ ranges[mid].orig_index)) -+ { -+ unsigned new_start = mid + 1; -+ n = start + n - new_start; -+ start = new_start; -+ } else -+ return (value - ranges[mid].start_value) + -+ ranges[mid].orig_index; -+ } -+ if (n > 0) { -+ unsigned start_orig_index = ranges[start].orig_index; -+ unsigned range_size = -+ ranges[start + 1].orig_index - start_orig_index; -+ -+ if (ranges[start].start_value <= value && -+ value < (int) (ranges[start].start_value + range_size)) -+ { -+ return (value - ranges[start].start_value) + -+ start_orig_index; -+ } -+ } -+ return -1; -+} -+ -+static size_t -+parse_tag_and_wiretype(size_t len, -+ const uint8_t *data, -+ uint32_t *tag_out, -+ ProtobufCWireType *wiretype_out) -+{ -+ unsigned max_rv = len > 5 ? 5 : len; -+ uint32_t tag = (data[0] & 0x7f) >> 3; -+ unsigned shift = 4; -+ unsigned rv; -+ -+ *wiretype_out = data[0] & 7; -+ if ((data[0] & 0x80) == 0) { -+ *tag_out = tag; -+ return 1; -+ } -+ for (rv = 1; rv < max_rv; rv++) { -+ if (data[rv] & 0x80) { -+ tag |= (data[rv] & 0x7f) << shift; -+ shift += 7; -+ } else { -+ tag |= data[rv] << shift; -+ *tag_out = tag; -+ return rv + 1; -+ } -+ } -+ return 0; /* error: bad header */ -+} -+ -+/* sizeof(ScannedMember) must be <= (1< len) { -+ PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val); -+ return 0; -+ } -+ return hdr_len + val; -+} -+ -+static size_t -+max_b128_numbers(size_t len, const uint8_t *data) -+{ -+ size_t rv = 0; -+ while (len--) -+ if ((*data++ & 0x80) == 0) -+ ++rv; -+ return rv; -+} -+ -+/**@}*/ -+ -+/** -+ * Merge earlier message into a latter message. -+ * -+ * For numeric types and strings, if the same value appears multiple -+ * times, the parser accepts the last value it sees. For embedded -+ * message fields, the parser merges multiple instances of the same -+ * field. That is, all singular scalar fields in the latter instance -+ * replace those in the former, singular embedded messages are merged, -+ * and repeated fields are concatenated. -+ * -+ * The earlier message should be freed after calling this function, as -+ * some of its fields may have been reused and changed to their default -+ * values during the merge. -+ */ -+static protobuf_c_boolean -+merge_messages(ProtobufCMessage *earlier_msg, -+ ProtobufCMessage *latter_msg, -+ ProtobufCAllocator *allocator) -+{ -+ unsigned i; -+ const ProtobufCFieldDescriptor *fields = -+ earlier_msg->descriptor->fields; -+ for (i = 0; i < latter_msg->descriptor->n_fields; i++) { -+ if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) { -+ size_t *n_earlier = -+ STRUCT_MEMBER_PTR(size_t, earlier_msg, -+ fields[i].quantifier_offset); -+ uint8_t **p_earlier = -+ STRUCT_MEMBER_PTR(uint8_t *, earlier_msg, -+ fields[i].offset); -+ size_t *n_latter = -+ STRUCT_MEMBER_PTR(size_t, latter_msg, -+ fields[i].quantifier_offset); -+ uint8_t **p_latter = -+ STRUCT_MEMBER_PTR(uint8_t *, latter_msg, -+ fields[i].offset); -+ -+ if (*n_earlier > 0) { -+ if (*n_latter > 0) { -+ /* Concatenate the repeated field */ -+ size_t el_size = -+ sizeof_elt_in_repeated_array(fields[i].type); -+ uint8_t *new_field; -+ -+ new_field = do_alloc(allocator, -+ (*n_earlier + *n_latter) * el_size); -+ if (!new_field) -+ return FALSE; -+ -+ memcpy(new_field, *p_earlier, -+ *n_earlier * el_size); -+ memcpy(new_field + -+ *n_earlier * el_size, -+ *p_latter, -+ *n_latter * el_size); -+ -+ do_free(allocator, *p_latter); -+ do_free(allocator, *p_earlier); -+ *p_latter = new_field; -+ *n_latter = *n_earlier + *n_latter; -+ } else { -+ /* Zero copy the repeated field from the earlier message */ -+ *n_latter = *n_earlier; -+ *p_latter = *p_earlier; -+ } -+ /* Make sure the field does not get double freed */ -+ *n_earlier = 0; -+ *p_earlier = 0; -+ } -+ } else if (fields[i].type == PROTOBUF_C_TYPE_MESSAGE) { -+ ProtobufCMessage **em = -+ STRUCT_MEMBER_PTR(ProtobufCMessage *, -+ earlier_msg, -+ fields[i].offset); -+ ProtobufCMessage **lm = -+ STRUCT_MEMBER_PTR(ProtobufCMessage *, -+ latter_msg, -+ fields[i].offset); -+ if (*em != NULL) { -+ if (*lm != NULL) { -+ if (!merge_messages -+ (*em, *lm, allocator)) -+ return FALSE; -+ } else { -+ /* Zero copy the optional message */ -+ assert(fields[i].label == -+ PROTOBUF_C_LABEL_OPTIONAL); -+ *lm = *em; -+ *em = NULL; -+ } -+ } -+ } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) { -+ size_t el_size = 0; -+ protobuf_c_boolean need_to_merge = FALSE; -+ void *earlier_elem = -+ STRUCT_MEMBER_P(earlier_msg, fields[i].offset); -+ void *latter_elem = -+ STRUCT_MEMBER_P(latter_msg, fields[i].offset); -+ const void *def_val = fields[i].default_value; -+ -+ switch (fields[i].type) { -+ case PROTOBUF_C_TYPE_BYTES: { -+ el_size = sizeof(ProtobufCBinaryData); -+ uint8_t *e_data = -+ ((ProtobufCBinaryData *) earlier_elem)->data; -+ uint8_t *l_data = -+ ((ProtobufCBinaryData *) latter_elem)->data; -+ const ProtobufCBinaryData *d_bd = -+ (ProtobufCBinaryData *) def_val; -+ -+ need_to_merge = -+ (e_data != NULL && -+ (d_bd != NULL && -+ e_data != d_bd->data)) && -+ (l_data == NULL || -+ (d_bd != NULL && -+ l_data == d_bd->data)); -+ break; -+ } -+ case PROTOBUF_C_TYPE_STRING: { -+ el_size = sizeof(char *); -+ char *e_str = *(char **) earlier_elem; -+ char *l_str = *(char **) latter_elem; -+ const char *d_str = def_val; -+ -+ need_to_merge = e_str != d_str && l_str == d_str; -+ break; -+ } -+ default: { -+ el_size = sizeof_elt_in_repeated_array(fields[i].type); -+ -+ need_to_merge = -+ STRUCT_MEMBER(protobuf_c_boolean, -+ earlier_msg, -+ fields[i].quantifier_offset) && -+ !STRUCT_MEMBER(protobuf_c_boolean, -+ latter_msg, -+ fields[i].quantifier_offset); -+ break; -+ } -+ } -+ -+ if (need_to_merge) { -+ memcpy(latter_elem, earlier_elem, el_size); -+ /* -+ * Reset the element from the old message to 0 -+ * to make sure earlier message deallocation -+ * doesn't corrupt zero-copied data in the new -+ * message, earlier message will be freed after -+ * this function is called anyway -+ */ -+ memset(earlier_elem, 0, el_size); -+ -+ if (fields[i].quantifier_offset != 0) { -+ /* Set the has field, if applicable */ -+ STRUCT_MEMBER(protobuf_c_boolean, -+ latter_msg, -+ fields[i]. -+ quantifier_offset) = TRUE; -+ STRUCT_MEMBER(protobuf_c_boolean, -+ earlier_msg, -+ fields[i]. -+ quantifier_offset) = FALSE; -+ } -+ } -+ } -+ } -+ return TRUE; -+} -+ -+/** -+ * Count packed elements. -+ * -+ * Given a raw slab of packed-repeated values, determine the number of -+ * elements. This function detects certain kinds of errors but not -+ * others; the remaining error checking is done by -+ * parse_packed_repeated_member(). -+ */ -+static protobuf_c_boolean -+count_packed_elements(ProtobufCType type, -+ size_t len, const uint8_t *data, size_t *count_out) -+{ -+ switch (type) { -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ if (len % 4 != 0) { -+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types"); -+ return FALSE; -+ } -+ *count_out = len / 4; -+ return TRUE; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ if (len % 8 != 0) { -+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types"); -+ return FALSE; -+ } -+ *count_out = len / 8; -+ return TRUE; -+ case PROTOBUF_C_TYPE_INT32: -+ case PROTOBUF_C_TYPE_SINT32: -+ case PROTOBUF_C_TYPE_ENUM: -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_SINT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ *count_out = max_b128_numbers(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_BOOL: -+ *count_out = len; -+ return TRUE; -+ case PROTOBUF_C_TYPE_STRING: -+ case PROTOBUF_C_TYPE_BYTES: -+ case PROTOBUF_C_TYPE_MESSAGE: -+ default: -+ PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type); -+ return FALSE; -+ } -+} -+ -+static inline uint32_t -+parse_uint32(unsigned len, const uint8_t *data) -+{ -+ uint32_t rv = data[0] & 0x7f; -+ if (len > 1) { -+ rv |= ((uint32_t) (data[1] & 0x7f) << 7); -+ if (len > 2) { -+ rv |= ((uint32_t) (data[2] & 0x7f) << 14); -+ if (len > 3) { -+ rv |= ((uint32_t) (data[3] & 0x7f) << 21); -+ if (len > 4) -+ rv |= ((uint32_t) (data[4]) << 28); -+ } -+ } -+ } -+ return rv; -+} -+ -+static inline uint32_t -+parse_int32(unsigned len, const uint8_t *data) -+{ -+ return parse_uint32(len, data); -+} -+ -+static inline int32_t -+unzigzag32(uint32_t v) -+{ -+ if (v & 1) -+ return -(v >> 1) - 1; -+ else -+ return v >> 1; -+} -+ -+static inline uint32_t -+parse_fixed_uint32(const uint8_t *data) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ uint32_t t; -+ memcpy(&t, data, 4); -+ return t; -+#else -+ return data[0] | -+ ((uint32_t) (data[1]) << 8) | -+ ((uint32_t) (data[2]) << 16) | -+ ((uint32_t) (data[3]) << 24); -+#endif -+} -+ -+static uint64_t -+parse_uint64(unsigned len, const uint8_t *data) -+{ -+ unsigned shift, i; -+ uint64_t rv; -+ -+ if (len < 5) -+ return parse_uint32(len, data); -+ rv = ((uint64_t) (data[0] & 0x7f)) | -+ ((uint64_t) (data[1] & 0x7f) << 7) | -+ ((uint64_t) (data[2] & 0x7f) << 14) | -+ ((uint64_t) (data[3] & 0x7f) << 21); -+ shift = 28; -+ for (i = 4; i < len; i++) { -+ rv |= (((uint64_t) (data[i] & 0x7f)) << shift); -+ shift += 7; -+ } -+ return rv; -+} -+ -+static inline int64_t -+unzigzag64(uint64_t v) -+{ -+ if (v & 1) -+ return -(v >> 1) - 1; -+ else -+ return v >> 1; -+} -+ -+static inline uint64_t -+parse_fixed_uint64(const uint8_t *data) -+{ -+#if !defined(WORDS_BIGENDIAN) -+ uint64_t t; -+ memcpy(&t, data, 8); -+ return t; -+#else -+ return (uint64_t) parse_fixed_uint32(data) | -+ (((uint64_t) parse_fixed_uint32(data + 4)) << 32); -+#endif -+} -+ -+static protobuf_c_boolean -+parse_boolean(unsigned len, const uint8_t *data) -+{ -+ unsigned i; -+ for (i = 0; i < len; i++) -+ if (data[i] & 0x7f) -+ return TRUE; -+ return FALSE; -+} -+ -+static protobuf_c_boolean -+parse_required_member(ScannedMember *scanned_member, -+ void *member, -+ ProtobufCAllocator *allocator, -+ protobuf_c_boolean maybe_clear) -+{ -+ unsigned len = scanned_member->len; -+ const uint8_t *data = scanned_member->data; -+ ProtobufCWireType wire_type = scanned_member->wire_type; -+ -+ switch (scanned_member->field->type) { -+ case PROTOBUF_C_TYPE_INT32: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(uint32_t *) member = parse_int32(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_UINT32: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(uint32_t *) member = parse_uint32(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_SINT32: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(int32_t *) member = unzigzag32(parse_uint32(len, data)); -+ return TRUE; -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT) -+ return FALSE; -+ *(uint32_t *) member = parse_fixed_uint32(data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(uint64_t *) member = parse_uint64(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_SINT64: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(int64_t *) member = unzigzag64(parse_uint64(len, data)); -+ return TRUE; -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT) -+ return FALSE; -+ *(uint64_t *) member = parse_fixed_uint64(data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_BOOL: -+ *(protobuf_c_boolean *) member = parse_boolean(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_ENUM: -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT) -+ return FALSE; -+ *(uint32_t *) member = parse_uint32(len, data); -+ return TRUE; -+ case PROTOBUF_C_TYPE_STRING: { -+ char **pstr = member; -+ unsigned pref_len = scanned_member->length_prefix_len; -+ -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -+ return FALSE; -+ -+ if (maybe_clear && *pstr != NULL) { -+ const char *def = scanned_member->field->default_value; -+ if (*pstr != NULL && *pstr != def) -+ do_free(allocator, *pstr); -+ } -+ *pstr = do_alloc(allocator, len - pref_len + 1); -+ if (*pstr == NULL) -+ return FALSE; -+ memcpy(*pstr, data + pref_len, len - pref_len); -+ (*pstr)[len - pref_len] = 0; -+ return TRUE; -+ } -+ case PROTOBUF_C_TYPE_BYTES: { -+ ProtobufCBinaryData *bd = member; -+ const ProtobufCBinaryData *def_bd; -+ unsigned pref_len = scanned_member->length_prefix_len; -+ -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -+ return FALSE; -+ -+ def_bd = scanned_member->field->default_value; -+ if (maybe_clear && -+ bd->data != NULL && -+ (def_bd == NULL || bd->data != def_bd->data)) -+ { -+ do_free(allocator, bd->data); -+ } -+ if (len - pref_len > 0) { -+ bd->data = do_alloc(allocator, len - pref_len); -+ if (bd->data == NULL) -+ return FALSE; -+ memcpy(bd->data, data + pref_len, len - pref_len); -+ } -+ bd->len = len - pref_len; -+ return TRUE; -+ } -+ case PROTOBUF_C_TYPE_MESSAGE: { -+ ProtobufCMessage **pmessage = member; -+ ProtobufCMessage *subm; -+ const ProtobufCMessage *def_mess; -+ protobuf_c_boolean merge_successful = TRUE; -+ unsigned pref_len = scanned_member->length_prefix_len; -+ -+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED) -+ return FALSE; -+ -+ def_mess = scanned_member->field->default_value; -+ subm = protobuf_c_message_unpack(scanned_member->field->descriptor, -+ allocator, -+ len - pref_len, -+ data + pref_len); -+ -+ if (maybe_clear && -+ *pmessage != NULL && -+ *pmessage != def_mess) -+ { -+ if (subm != NULL) -+ merge_successful = merge_messages(*pmessage, subm, allocator); -+ /* Delete the previous message */ -+ protobuf_c_message_free_unpacked(*pmessage, allocator); -+ } -+ *pmessage = subm; -+ if (subm == NULL || !merge_successful) -+ return FALSE; -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ -+static protobuf_c_boolean -+parse_optional_member(ScannedMember *scanned_member, -+ void *member, -+ ProtobufCMessage *message, -+ ProtobufCAllocator *allocator) -+{ -+ if (!parse_required_member(scanned_member, member, allocator, TRUE)) -+ return FALSE; -+ if (scanned_member->field->quantifier_offset != 0) -+ STRUCT_MEMBER(protobuf_c_boolean, -+ message, -+ scanned_member->field->quantifier_offset) = TRUE; -+ return TRUE; -+} -+ -+static protobuf_c_boolean -+parse_repeated_member(ScannedMember *scanned_member, -+ void *member, -+ ProtobufCMessage *message, -+ ProtobufCAllocator *allocator) -+{ -+ const ProtobufCFieldDescriptor *field = scanned_member->field; -+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); -+ size_t siz = sizeof_elt_in_repeated_array(field->type); -+ char *array = *(char **) member; -+ -+ if (!parse_required_member(scanned_member, array + siz * (*p_n), -+ allocator, FALSE)) -+ { -+ return FALSE; -+ } -+ *p_n += 1; -+ return TRUE; -+} -+ -+static unsigned -+scan_varint(unsigned len, const uint8_t *data) -+{ -+ unsigned i; -+ if (len > 10) -+ len = 10; -+ for (i = 0; i < len; i++) -+ if ((data[i] & 0x80) == 0) -+ break; -+ if (i == len) -+ return 0; -+ return i + 1; -+} -+ -+static protobuf_c_boolean -+parse_packed_repeated_member(ScannedMember *scanned_member, -+ void *member, -+ ProtobufCMessage *message) -+{ -+ const ProtobufCFieldDescriptor *field = scanned_member->field; -+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset); -+ size_t siz = sizeof_elt_in_repeated_array(field->type); -+ void *array = *(void **) member + siz * (*p_n); -+ const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len; -+ size_t rem = scanned_member->len - scanned_member->length_prefix_len; -+ size_t count = 0; -+ unsigned i; -+ -+ switch (field->type) { -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ count = (scanned_member->len - scanned_member->length_prefix_len) / 4; -+#if !defined(WORDS_BIGENDIAN) -+ goto no_unpacking_needed; -+#else -+ for (i = 0; i < count; i++) { -+ ((uint32_t *) array)[i] = parse_fixed_uint32(at); -+ at += 4; -+ } -+ break; -+#endif -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ count = (scanned_member->len - scanned_member->length_prefix_len) / 8; -+#if !defined(WORDS_BIGENDIAN) -+ goto no_unpacking_needed; -+#else -+ for (i = 0; i < count; i++) { -+ ((uint64_t *) array)[i] = parse_fixed_uint64(at); -+ at += 8; -+ } -+ break; -+#endif -+ case PROTOBUF_C_TYPE_INT32: -+ while (rem > 0) { -+ unsigned s = scan_varint(rem, at); -+ if (s == 0) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value"); -+ return FALSE; -+ } -+ ((int32_t *) array)[count++] = parse_int32(s, at); -+ at += s; -+ rem -= s; -+ } -+ break; -+ case PROTOBUF_C_TYPE_SINT32: -+ while (rem > 0) { -+ unsigned s = scan_varint(rem, at); -+ if (s == 0) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value"); -+ return FALSE; -+ } -+ ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at)); -+ at += s; -+ rem -= s; -+ } -+ break; -+ case PROTOBUF_C_TYPE_ENUM: -+ case PROTOBUF_C_TYPE_UINT32: -+ while (rem > 0) { -+ unsigned s = scan_varint(rem, at); -+ if (s == 0) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value"); -+ return FALSE; -+ } -+ ((uint32_t *) array)[count++] = parse_uint32(s, at); -+ at += s; -+ rem -= s; -+ } -+ break; -+ -+ case PROTOBUF_C_TYPE_SINT64: -+ while (rem > 0) { -+ unsigned s = scan_varint(rem, at); -+ if (s == 0) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value"); -+ return FALSE; -+ } -+ ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at)); -+ at += s; -+ rem -= s; -+ } -+ break; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_UINT64: -+ while (rem > 0) { -+ unsigned s = scan_varint(rem, at); -+ if (s == 0) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value"); -+ return FALSE; -+ } -+ ((int64_t *) array)[count++] = parse_uint64(s, at); -+ at += s; -+ rem -= s; -+ } -+ break; -+ case PROTOBUF_C_TYPE_BOOL: -+ count = rem; -+ for (i = 0; i < count; i++) { -+ if (at[i] > 1) { -+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value"); -+ return FALSE; -+ } -+ ((protobuf_c_boolean *) array)[i] = at[i]; -+ } -+ break; -+ default: -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ } -+ *p_n += count; -+ return TRUE; -+ -+#if !defined(WORDS_BIGENDIAN) -+no_unpacking_needed: -+ memcpy(array, at, count * siz); -+ *p_n += count; -+ return TRUE; -+#endif -+} -+ -+static protobuf_c_boolean -+is_packable_type(ProtobufCType type) -+{ -+ return -+ type != PROTOBUF_C_TYPE_STRING && -+ type != PROTOBUF_C_TYPE_BYTES && -+ type != PROTOBUF_C_TYPE_MESSAGE; -+} -+ -+static protobuf_c_boolean -+parse_member(ScannedMember *scanned_member, -+ ProtobufCMessage *message, -+ ProtobufCAllocator *allocator) -+{ -+ const ProtobufCFieldDescriptor *field = scanned_member->field; -+ void *member; -+ -+ if (field == NULL) { -+ ProtobufCMessageUnknownField *ufield = -+ message->unknown_fields + -+ (message->n_unknown_fields++); -+ ufield->tag = scanned_member->tag; -+ ufield->wire_type = scanned_member->wire_type; -+ ufield->len = scanned_member->len; -+ ufield->data = do_alloc(allocator, scanned_member->len); -+ if (ufield->data == NULL) -+ return FALSE; -+ memcpy(ufield->data, scanned_member->data, ufield->len); -+ return TRUE; -+ } -+ member = (char *) message + field->offset; -+ switch (field->label) { -+ case PROTOBUF_C_LABEL_REQUIRED: -+ return parse_required_member(scanned_member, member, -+ allocator, TRUE); -+ case PROTOBUF_C_LABEL_OPTIONAL: -+ return parse_optional_member(scanned_member, member, -+ message, allocator); -+ case PROTOBUF_C_LABEL_REPEATED: -+ if (scanned_member->wire_type == -+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && -+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || -+ is_packable_type(field->type))) -+ { -+ return parse_packed_repeated_member(scanned_member, -+ member, message); -+ } else { -+ return parse_repeated_member(scanned_member, -+ member, message, -+ allocator); -+ } -+ } -+ PROTOBUF_C__ASSERT_NOT_REACHED(); -+ return 0; -+} -+ -+/** -+ * Initialise messages generated by old code. -+ * -+ * This function is used if desc->message_init == NULL (which occurs -+ * for old code, and which would be useful to support allocating -+ * descriptors dynamically). -+ */ -+static void -+message_init_generic(const ProtobufCMessageDescriptor *desc, -+ ProtobufCMessage *message) -+{ -+ unsigned i; -+ -+ memset(message, 0, desc->sizeof_message); -+ message->descriptor = desc; -+ for (i = 0; i < desc->n_fields; i++) { -+ if (desc->fields[i].default_value != NULL && -+ desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED) -+ { -+ void *field = -+ STRUCT_MEMBER_P(message, desc->fields[i].offset); -+ const void *dv = desc->fields[i].default_value; -+ -+ switch (desc->fields[i].type) { -+ case PROTOBUF_C_TYPE_INT32: -+ case PROTOBUF_C_TYPE_SINT32: -+ case PROTOBUF_C_TYPE_SFIXED32: -+ case PROTOBUF_C_TYPE_UINT32: -+ case PROTOBUF_C_TYPE_FIXED32: -+ case PROTOBUF_C_TYPE_FLOAT: -+ case PROTOBUF_C_TYPE_ENUM: -+ memcpy(field, dv, 4); -+ break; -+ case PROTOBUF_C_TYPE_INT64: -+ case PROTOBUF_C_TYPE_SINT64: -+ case PROTOBUF_C_TYPE_SFIXED64: -+ case PROTOBUF_C_TYPE_UINT64: -+ case PROTOBUF_C_TYPE_FIXED64: -+ case PROTOBUF_C_TYPE_DOUBLE: -+ memcpy(field, dv, 8); -+ break; -+ case PROTOBUF_C_TYPE_BOOL: -+ memcpy(field, dv, sizeof(protobuf_c_boolean)); -+ break; -+ case PROTOBUF_C_TYPE_BYTES: -+ memcpy(field, dv, sizeof(ProtobufCBinaryData)); -+ break; -+ -+ case PROTOBUF_C_TYPE_STRING: -+ case PROTOBUF_C_TYPE_MESSAGE: -+ /* -+ * The next line essentially implements a cast -+ * from const, which is totally unavoidable. -+ */ -+ *(const void **) field = dv; -+ break; -+ } -+ } -+ } -+} -+ -+/**@}*/ -+ -+/* -+ * ScannedMember slabs (an unpacking implementation detail). Before doing real -+ * unpacking, we first scan through the elements to see how many there are (for -+ * repeated fields), and which field to use (for non-repeated fields given -+ * twice). -+ * -+ * In order to avoid allocations for small messages, we keep a stack-allocated -+ * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we -+ * fill that up, we allocate each slab twice as large as the previous one. -+ */ -+#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4 -+ -+/* -+ * The number of slabs, including the stack-allocated ones; choose the number so -+ * that we would overflow if we needed a slab larger than provided. -+ */ -+#define MAX_SCANNED_MEMBER_SLAB \ -+ (sizeof(unsigned int)*8 - 1 \ -+ - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \ -+ - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2) -+ -+#define REQUIRED_FIELD_BITMAP_SET(index) \ -+ (required_fields_bitmap[(index)/8] |= (1<<((index)%8))) -+ -+#define REQUIRED_FIELD_BITMAP_IS_SET(index) \ -+ (required_fields_bitmap[(index)/8] & (1<<((index)%8))) -+ -+ProtobufCMessage * -+protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc, -+ ProtobufCAllocator *allocator, -+ size_t len, const uint8_t *data) -+{ -+ ProtobufCMessage *rv; -+ size_t rem = len; -+ const uint8_t *at = data; -+ const ProtobufCFieldDescriptor *last_field = desc->fields + 0; -+ ScannedMember first_member_slab[1 << -+ FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2]; -+ -+ /* -+ * scanned_member_slabs[i] is an array of arrays of ScannedMember. -+ * The first slab (scanned_member_slabs[0] is just a pointer to -+ * first_member_slab), above. All subsequent slabs will be allocated -+ * using the allocator. -+ */ -+ ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1]; -+ unsigned which_slab = 0; /* the slab we are currently populating */ -+ unsigned in_slab_index = 0; /* number of members in the slab */ -+ size_t n_unknown = 0; -+ unsigned f; -+ unsigned j; -+ unsigned i_slab; -+ unsigned last_field_index = 0; -+ unsigned required_fields_bitmap_len; -+ unsigned char required_fields_bitmap_stack[16]; -+ unsigned char *required_fields_bitmap = required_fields_bitmap_stack; -+ protobuf_c_boolean required_fields_bitmap_alloced = FALSE; -+ -+ ASSERT_IS_MESSAGE_DESCRIPTOR(desc); -+ -+ if (allocator == NULL) -+ allocator = &protobuf_c__allocator; -+ -+ rv = do_alloc(allocator, desc->sizeof_message); -+ if (!rv) -+ return (NULL); -+ scanned_member_slabs[0] = first_member_slab; -+ -+ required_fields_bitmap_len = (desc->n_fields + 7) / 8; -+ if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) { -+ required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len); -+ if (!required_fields_bitmap) { -+ do_free(allocator, rv); -+ return (NULL); -+ } -+ required_fields_bitmap_alloced = TRUE; -+ } -+ memset(required_fields_bitmap, 0, required_fields_bitmap_len); -+ -+ /* -+ * Generated code always defines "message_init". However, we provide a -+ * fallback for (1) users of old protobuf-c generated-code that do not -+ * provide the function, and (2) descriptors constructed from some other -+ * source (most likely, direct construction from the .proto file). -+ */ -+ if (desc->message_init != NULL) -+ protobuf_c_message_init(desc, rv); -+ else -+ message_init_generic(desc, rv); -+ -+ while (rem > 0) { -+ uint32_t tag; -+ ProtobufCWireType wire_type; -+ size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type); -+ const ProtobufCFieldDescriptor *field; -+ ScannedMember tmp; -+ -+ if (used == 0) { -+ PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u", -+ (unsigned) (at - data)); -+ goto error_cleanup_during_scan; -+ } -+ /* -+ * \todo Consider optimizing for field[1].id == tag, if field[1] -+ * exists! -+ */ -+ if (last_field == NULL || last_field->id != tag) { -+ /* lookup field */ -+ int field_index = -+ int_range_lookup(desc->n_field_ranges, -+ desc->field_ranges, -+ tag); -+ if (field_index < 0) { -+ field = NULL; -+ n_unknown++; -+ } else { -+ field = desc->fields + field_index; -+ last_field = field; -+ last_field_index = field_index; -+ } -+ } else { -+ field = last_field; -+ } -+ -+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED) -+ REQUIRED_FIELD_BITMAP_SET(last_field_index); -+ -+ at += used; -+ rem -= used; -+ tmp.tag = tag; -+ tmp.wire_type = wire_type; -+ tmp.field = field; -+ tmp.data = at; -+ tmp.length_prefix_len = 0; -+ -+ switch (wire_type) { -+ case PROTOBUF_C_WIRE_TYPE_VARINT: { -+ unsigned max_len = rem < 10 ? rem : 10; -+ unsigned i; -+ -+ for (i = 0; i < max_len; i++) -+ if ((at[i] & 0x80) == 0) -+ break; -+ if (i == max_len) { -+ PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u", -+ (unsigned) (at - data)); -+ goto error_cleanup_during_scan; -+ } -+ tmp.len = i + 1; -+ break; -+ } -+ case PROTOBUF_C_WIRE_TYPE_64BIT: -+ if (rem < 8) { -+ PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u", -+ (unsigned) (at - data)); -+ goto error_cleanup_during_scan; -+ } -+ tmp.len = 8; -+ break; -+ case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: { -+ size_t pref_len; -+ -+ tmp.len = scan_length_prefixed_data(rem, at, &pref_len); -+ if (tmp.len == 0) { -+ /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */ -+ goto error_cleanup_during_scan; -+ } -+ tmp.length_prefix_len = pref_len; -+ break; -+ } -+ case PROTOBUF_C_WIRE_TYPE_32BIT: -+ if (rem < 4) { -+ PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u", -+ (unsigned) (at - data)); -+ goto error_cleanup_during_scan; -+ } -+ tmp.len = 4; -+ break; -+ default: -+ PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u", -+ wire_type, (unsigned) (at - data)); -+ goto error_cleanup_during_scan; -+ } -+ -+ if (in_slab_index == (1U << -+ (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2))) -+ { -+ size_t size; -+ -+ in_slab_index = 0; -+ if (which_slab == MAX_SCANNED_MEMBER_SLAB) { -+ PROTOBUF_C_UNPACK_ERROR("too many fields"); -+ goto error_cleanup_during_scan; -+ } -+ which_slab++; -+ size = sizeof(ScannedMember) -+ << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2); -+ scanned_member_slabs[which_slab] = do_alloc(allocator, size); -+ if (scanned_member_slabs[which_slab] == NULL) -+ goto error_cleanup_during_scan; -+ } -+ scanned_member_slabs[which_slab][in_slab_index++] = tmp; -+ -+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) { -+ size_t *n = STRUCT_MEMBER_PTR(size_t, rv, -+ field->quantifier_offset); -+ if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED && -+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) || -+ is_packable_type(field->type))) -+ { -+ size_t count; -+ if (!count_packed_elements(field->type, -+ tmp.len - -+ tmp.length_prefix_len, -+ tmp.data + -+ tmp.length_prefix_len, -+ &count)) -+ { -+ PROTOBUF_C_UNPACK_ERROR("counting packed elements"); -+ goto error_cleanup_during_scan; -+ } -+ *n += count; -+ } else { -+ *n += 1; -+ } -+ } -+ -+ at += tmp.len; -+ rem -= tmp.len; -+ } -+ -+ /* allocate space for repeated fields, also check that all required fields have been set */ -+ for (f = 0; f < desc->n_fields; f++) { -+ const ProtobufCFieldDescriptor *field = desc->fields + f; -+ if (field->label == PROTOBUF_C_LABEL_REPEATED) { -+ size_t siz = -+ sizeof_elt_in_repeated_array(field->type); -+ size_t *n_ptr = -+ STRUCT_MEMBER_PTR(size_t, rv, -+ field->quantifier_offset); -+ if (*n_ptr != 0) { -+ unsigned n = *n_ptr; -+ *n_ptr = 0; -+ assert(rv->descriptor != NULL); -+#define CLEAR_REMAINING_N_PTRS() \ -+ for(f++;f < desc->n_fields; f++) \ -+ { \ -+ field = desc->fields + f; \ -+ if (field->label == PROTOBUF_C_LABEL_REPEATED) \ -+ STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \ -+ } -+ void *a = do_alloc(allocator, siz * n); -+ if (!a) { -+ CLEAR_REMAINING_N_PTRS(); -+ goto error_cleanup; -+ } -+ STRUCT_MEMBER(void *, rv, field->offset) = a; -+ } -+ } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) { -+ if (field->default_value == NULL && -+ !REQUIRED_FIELD_BITMAP_IS_SET(f)) -+ { -+ CLEAR_REMAINING_N_PTRS(); -+ PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'", -+ desc->name, field->name); -+ goto error_cleanup; -+ } -+ } -+ } -+#undef CLEAR_REMAINING_N_PTRS -+ -+ /* allocate space for unknown fields */ -+ if (n_unknown) { -+ rv->unknown_fields = do_alloc(allocator, -+ n_unknown * sizeof(ProtobufCMessageUnknownField)); -+ if (rv->unknown_fields == NULL) -+ goto error_cleanup; -+ } -+ -+ /* do real parsing */ -+ for (i_slab = 0; i_slab <= which_slab; i_slab++) { -+ unsigned max = (i_slab == which_slab) ? -+ in_slab_index : (1U << (i_slab + 4)); -+ ScannedMember *slab = scanned_member_slabs[i_slab]; -+ unsigned j; -+ -+ for (j = 0; j < max; j++) { -+ if (!parse_member(slab + j, rv, allocator)) { -+ PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s", -+ slab->field ? slab->field->name : "*unknown-field*", -+ desc->name); -+ goto error_cleanup; -+ } -+ } -+ } -+ -+ /* cleanup */ -+ for (j = 1; j <= which_slab; j++) -+ do_free(allocator, scanned_member_slabs[j]); -+ if (required_fields_bitmap_alloced) -+ do_free(allocator, required_fields_bitmap); -+ return rv; -+ -+error_cleanup: -+ protobuf_c_message_free_unpacked(rv, allocator); -+ for (j = 1; j <= which_slab; j++) -+ do_free(allocator, scanned_member_slabs[j]); -+ if (required_fields_bitmap_alloced) -+ do_free(allocator, required_fields_bitmap); -+ return NULL; -+ -+error_cleanup_during_scan: -+ do_free(allocator, rv); -+ for (j = 1; j <= which_slab; j++) -+ do_free(allocator, scanned_member_slabs[j]); -+ if (required_fields_bitmap_alloced) -+ do_free(allocator, required_fields_bitmap); -+ return NULL; -+} -+ -+void -+protobuf_c_message_free_unpacked(ProtobufCMessage *message, -+ ProtobufCAllocator *allocator) -+{ -+ const ProtobufCMessageDescriptor *desc = message->descriptor; -+ unsigned f; -+ -+ ASSERT_IS_MESSAGE(message); -+ if (allocator == NULL) -+ allocator = &protobuf_c__allocator; -+ message->descriptor = NULL; -+ for (f = 0; f < desc->n_fields; f++) { -+ if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) { -+ size_t n = STRUCT_MEMBER(size_t, -+ message, -+ desc->fields[f].quantifier_offset); -+ void *arr = STRUCT_MEMBER(void *, -+ message, -+ desc->fields[f].offset); -+ -+ if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { -+ unsigned i; -+ for (i = 0; i < n; i++) -+ do_free(allocator, ((char **) arr)[i]); -+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { -+ unsigned i; -+ for (i = 0; i < n; i++) -+ do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data); -+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { -+ unsigned i; -+ for (i = 0; i < n; i++) -+ protobuf_c_message_free_unpacked( -+ ((ProtobufCMessage **) arr)[i], -+ allocator -+ ); -+ } -+ if (arr != NULL) -+ do_free(allocator, arr); -+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) { -+ char *str = STRUCT_MEMBER(char *, message, -+ desc->fields[f].offset); -+ -+ if (str && str != desc->fields[f].default_value) -+ do_free(allocator, str); -+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) { -+ void *data = STRUCT_MEMBER(ProtobufCBinaryData, message, -+ desc->fields[f].offset).data; -+ const ProtobufCBinaryData *default_bd; -+ -+ default_bd = desc->fields[f].default_value; -+ if (data != NULL && -+ (default_bd == NULL || -+ default_bd->data != data)) -+ { -+ do_free(allocator, data); -+ } -+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) { -+ ProtobufCMessage *sm; -+ -+ sm = STRUCT_MEMBER(ProtobufCMessage *, message, -+ desc->fields[f].offset); -+ if (sm && sm != desc->fields[f].default_value) -+ protobuf_c_message_free_unpacked(sm, allocator); -+ } -+ } -+ -+ for (f = 0; f < message->n_unknown_fields; f++) -+ do_free(allocator, message->unknown_fields[f].data); -+ if (message->unknown_fields != NULL) -+ do_free(allocator, message->unknown_fields); -+ -+ do_free(allocator, message); -+} -+ -+void -+protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor, -+ void *message) -+{ -+ descriptor->message_init((ProtobufCMessage *) (message)); -+} -+ -+protobuf_c_boolean -+protobuf_c_message_check(const ProtobufCMessage *message) -+{ -+ if (!message || -+ !message->descriptor || -+ message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC) -+ { -+ return FALSE; -+ } -+ -+ unsigned i; -+ for (i = 0; i < message->descriptor->n_fields; i++) { -+ const ProtobufCFieldDescriptor *f = message->descriptor->fields + i; -+ ProtobufCType type = f->type; -+ ProtobufCLabel label = f->label; -+ void *field = STRUCT_MEMBER_P (message, f->offset); -+ -+ if (label == PROTOBUF_C_LABEL_REPEATED) { -+ size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset); -+ -+ if (*quantity > 0 && *(void **) field == NULL) { -+ return FALSE; -+ } -+ -+ if (type == PROTOBUF_C_TYPE_MESSAGE) { -+ ProtobufCMessage **submessage = *(ProtobufCMessage ***) field; -+ unsigned j; -+ for (j = 0; j < *quantity; j++) { -+ if (!protobuf_c_message_check(submessage[j])) -+ return FALSE; -+ } -+ } else if (type == PROTOBUF_C_TYPE_STRING) { -+ char **string = *(char ***) field; -+ unsigned j; -+ for (j = 0; j < *quantity; j++) { -+ if (!string[j]) -+ return FALSE; -+ } -+ } else if (type == PROTOBUF_C_TYPE_BYTES) { -+ ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field; -+ unsigned j; -+ for (j = 0; j < *quantity; j++) { -+ if (bd[j].len > 0 && bd[j].data == NULL) -+ return FALSE; -+ } -+ } -+ -+ } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */ -+ -+ if (type == PROTOBUF_C_TYPE_MESSAGE) { -+ ProtobufCMessage *submessage = *(ProtobufCMessage **) field; -+ if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) { -+ if (!protobuf_c_message_check(submessage)) -+ return FALSE; -+ } -+ } else if (type == PROTOBUF_C_TYPE_STRING) { -+ char *string = *(char **) field; -+ if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL) -+ return FALSE; -+ } else if (type == PROTOBUF_C_TYPE_BYTES) { -+ protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset); -+ ProtobufCBinaryData *bd = field; -+ if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) { -+ if (bd->len > 0 && bd->data == NULL) -+ return FALSE; -+ } -+ } -+ } -+ } -+ -+ return TRUE; -+} -+ -+/* === services === */ -+ -+typedef void (*GenericHandler) (void *service, -+ const ProtobufCMessage *input, -+ ProtobufCClosure closure, -+ void *closure_data); -+void -+protobuf_c_service_invoke_internal(ProtobufCService *service, -+ unsigned method_index, -+ const ProtobufCMessage *input, -+ ProtobufCClosure closure, -+ void *closure_data) -+{ -+ GenericHandler *handlers; -+ GenericHandler handler; -+ -+ /* -+ * Verify that method_index is within range. If this fails, you are -+ * likely invoking a newly added method on an old service. (Although -+ * other memory corruption bugs can cause this assertion too.) -+ */ -+ assert(method_index < service->descriptor->n_methods); -+ -+ /* -+ * Get the array of virtual methods (which are enumerated by the -+ * generated code). -+ */ -+ handlers = (GenericHandler *) (service + 1); -+ -+ /* -+ * Get our method and invoke it. -+ * \todo Seems like handler == NULL is a situation that needs handling. -+ */ -+ handler = handlers[method_index]; -+ (*handler)(service, input, closure, closure_data); -+} -+ -+void -+protobuf_c_service_generated_init(ProtobufCService *service, -+ const ProtobufCServiceDescriptor *descriptor, -+ ProtobufCServiceDestroy destroy) -+{ -+ ASSERT_IS_SERVICE_DESCRIPTOR(descriptor); -+ service->descriptor = descriptor; -+ service->destroy = destroy; -+ service->invoke = protobuf_c_service_invoke_internal; -+ memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); -+} -+ -+void protobuf_c_service_destroy(ProtobufCService *service) -+{ -+ service->destroy(service); -+} -+ -+/* --- querying the descriptors --- */ -+ -+const ProtobufCEnumValue * -+protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc, -+ const char *name) -+{ -+ unsigned start = 0; -+ unsigned count = desc->n_value_names; -+ -+ while (count > 1) { -+ unsigned mid = start + count / 2; -+ int rv = strcmp(desc->values_by_name[mid].name, name); -+ if (rv == 0) -+ return desc->values + desc->values_by_name[mid].index; -+ else if (rv < 0) { -+ count = start + count - (mid + 1); -+ start = mid + 1; -+ } else -+ count = mid - start; -+ } -+ if (count == 0) -+ return NULL; -+ if (strcmp(desc->values_by_name[start].name, name) == 0) -+ return desc->values + desc->values_by_name[start].index; -+ return NULL; -+} -+ -+const ProtobufCEnumValue * -+protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc, -+ int value) -+{ -+ int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value); -+ if (rv < 0) -+ return NULL; -+ return desc->values + rv; -+} -+ -+const ProtobufCFieldDescriptor * -+protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc, -+ const char *name) -+{ -+ unsigned start = 0; -+ unsigned count = desc->n_fields; -+ const ProtobufCFieldDescriptor *field; -+ -+ while (count > 1) { -+ unsigned mid = start + count / 2; -+ int rv; -+ field = desc->fields + desc->fields_sorted_by_name[mid]; -+ rv = strcmp(field->name, name); -+ if (rv == 0) -+ return field; -+ else if (rv < 0) { -+ count = start + count - (mid + 1); -+ start = mid + 1; -+ } else -+ count = mid - start; -+ } -+ if (count == 0) -+ return NULL; -+ field = desc->fields + desc->fields_sorted_by_name[start]; -+ if (strcmp(field->name, name) == 0) -+ return field; -+ return NULL; -+} -+ -+const ProtobufCFieldDescriptor * -+protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc, -+ unsigned value) -+{ -+ int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value); -+ if (rv < 0) -+ return NULL; -+ return desc->fields + rv; -+} -+ -+const ProtobufCMethodDescriptor * -+protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc, -+ const char *name) -+{ -+ unsigned start = 0; -+ unsigned count = desc->n_methods; -+ -+ while (count > 1) { -+ unsigned mid = start + count / 2; -+ unsigned mid_index = desc->method_indices_by_name[mid]; -+ const char *mid_name = desc->methods[mid_index].name; -+ int rv = strcmp(mid_name, name); -+ -+ if (rv == 0) -+ return desc->methods + desc->method_indices_by_name[mid]; -+ if (rv < 0) { -+ count = start + count - (mid + 1); -+ start = mid + 1; -+ } else { -+ count = mid - start; -+ } -+ } -+ if (count == 0) -+ return NULL; -+ if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0) -+ return desc->methods + desc->method_indices_by_name[start]; -+ return NULL; -+} -diff --git a/src/protobuf/protobuf-c/protobuf-c.h b/src/protobuf/protobuf-c/protobuf-c.h -new file mode 100644 -index 0000000..593df2d ---- /dev/null -+++ b/src/protobuf/protobuf-c/protobuf-c.h -@@ -0,0 +1,1079 @@ -+/* -+ * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are -+ * met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * * Redistributions in binary form must reproduce the above -+ * copyright notice, this list of conditions and the following disclaimer -+ * in the documentation and/or other materials provided with the -+ * distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/*! \file -+ * \mainpage Introduction -+ * -+ * This is [protobuf-c], a C implementation of [Protocol Buffers]. -+ * -+ * This file defines the public API for the `libprotobuf-c` support library. -+ * This API includes interfaces that can be used directly by client code as well -+ * as the interfaces used by the code generated by the `protoc-c` compiler. -+ * -+ * The `libprotobuf-c` support library performs the actual serialization and -+ * deserialization of Protocol Buffers messages. It interacts with structures, -+ * definitions, and metadata generated by the `protoc-c` compiler from .proto -+ * files. -+ * -+ * \authors Dave Benson and the `protobuf-c` authors. -+ * -+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license. -+ * -+ * [protobuf-c]: https://github.com/protobuf-c/protobuf-c -+ * [Protocol Buffers]: https://developers.google.com/protocol-buffers/ -+ * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause -+ * -+ * \page gencode Generated Code -+ * -+ * For each enum, we generate a C enum. For each message, we generate a C -+ * structure which can be cast to a `ProtobufCMessage`. -+ * -+ * For each enum and message, we generate a descriptor object that allows us to -+ * implement a kind of reflection on the structures. -+ * -+ * First, some naming conventions: -+ * -+ * - The name of the type for enums and messages and services is camel case -+ * (meaning WordsAreCrammedTogether) except that double underscores are used -+ * to delimit scopes. For example, the following `.proto` file: -+ * -+~~~{.proto} -+ package foo.bar; -+ message BazBah { -+ optional int32 val = 1; -+ } -+~~~ -+ * -+ * would generate a C type `Foo__Bar__BazBah`. -+ * -+ * - Identifiers for functions and globals are all lowercase, with camel case -+ * words separated by single underscores. For example, one of the function -+ * prototypes generated by `protoc-c` for the above example: -+ * -+~~~{.c} -+Foo__Bar__BazBah * -+ foo__bar__baz_bah__unpack -+ (ProtobufCAllocator *allocator, -+ size_t len, -+ const uint8_t *data); -+~~~ -+ * -+ * - Identifiers for enum values contain an uppercase prefix which embeds the -+ * package name and the enum type name. -+ * -+ * - A double underscore is used to separate further components of identifier -+ * names. -+ * -+ * For example, in the name of the unpack function above, the package name -+ * `foo.bar` has become `foo__bar`, the message name BazBah has become -+ * `baz_bah`, and the method name is `unpack`. These are all joined with double -+ * underscores to form the C identifier `foo__bar__baz_bah__unpack`. -+ * -+ * We also generate descriptor objects for messages and enums. These are -+ * declared in the `.pb-c.h` files: -+ * -+~~~{.c} -+extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor; -+~~~ -+ * -+ * The message structures all begin with `ProtobufCMessageDescriptor *` which is -+ * sufficient to allow them to be cast to `ProtobufCMessage`. -+ * -+ * For each message defined in a `.proto` file, we generate a number of -+ * functions. Each function name contains a prefix based on the package name and -+ * message name in order to make it a unique C identifier. -+ * -+ * - `unpack()`. Unpacks data for a particular message format. Note that the -+ * `allocator` parameter is usually `NULL` to indicate that the system's -+ * `malloc()` and `free()` functions should be used for dynamically allocating -+ * memory. -+ * -+~~~{.c} -+Foo__Bar__BazBah * -+ foo__bar__baz_bah__unpack -+ (ProtobufCAllocator *allocator, -+ size_t len, -+ const uint8_t *data); -+~~~ -+ * -+ * - `free_unpacked()`. Frees a message object obtained with the `unpack()` -+ * method. -+ * -+~~~{.c} -+void foo__bar__baz_bah__free_unpacked -+ (Foo__Bar__BazBah *message, -+ ProtobufCAllocator *allocator); -+~~~ -+ * -+ * - `get_packed_size()`. Calculates the length in bytes of the serialized -+ * representation of the message object. -+ * -+~~~{.c} -+size_t foo__bar__baz_bah__get_packed_size -+ (const Foo__Bar__BazBah *message); -+~~~ -+ * -+ * - `pack()`. Pack a message object into a preallocated buffer. Assumes that -+ * the buffer is large enough. (Use `get_packed_size()` first.) -+ * -+~~~{.c} -+size_t foo__bar__baz_bah__pack -+ (const Foo__Bar__BazBah *message, -+ uint8_t *out); -+~~~ -+ * -+ * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an -+ * object which defines an "append bytes" callback to consume data as it is -+ * serialized. -+ * -+~~~{.c} -+size_t foo__bar__baz_bah__pack_to_buffer -+ (const Foo__Bar__BazBah *message, -+ ProtobufCBuffer *buffer); -+~~~ -+ * -+ * \page pack Packing and unpacking messages -+ * -+ * To pack a message, first compute the packed size of the message with -+ * protobuf_c_message_get_packed_size(), then allocate a buffer of at least -+ * that size, then call protobuf_c_message_pack(). -+ * -+ * Alternatively, a message can be serialized without calculating the final size -+ * first. Use the protobuf_c_message_pack_to_buffer() function and provide a -+ * ProtobufCBuffer object which implements an "append" method that consumes -+ * data. -+ * -+ * To unpack a message, call the protobuf_c_message_unpack() function. The -+ * result can be cast to an object of the type that matches the descriptor for -+ * the message. -+ * -+ * The result of unpacking a message should be freed with -+ * protobuf_c_message_free_unpacked(). -+ */ -+ -+#ifndef PROTOBUF_C_H -+#define PROTOBUF_C_H -+ -+#include -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+# define PROTOBUF_C__BEGIN_DECLS extern "C" { -+# define PROTOBUF_C__END_DECLS } -+#else -+# define PROTOBUF_C__BEGIN_DECLS -+# define PROTOBUF_C__END_DECLS -+#endif -+ -+PROTOBUF_C__BEGIN_DECLS -+ -+#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB) -+# ifdef PROTOBUF_C_EXPORT -+# define PROTOBUF_C__API __declspec(dllexport) -+# else -+# define PROTOBUF_C__API __declspec(dllimport) -+# endif -+#else -+# define PROTOBUF_C__API -+#endif -+ -+#if !defined(PROTOBUF_C__NO_DEPRECATED) -+# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -+# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__)) -+# endif -+#else -+# define PROTOBUF_C__DEPRECATED -+#endif -+ -+#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE -+ #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \ -+ , _##enum_name##_IS_INT_SIZE = INT_MAX -+#endif -+ -+#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3 -+#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9 -+#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af -+ -+/** -+ * \defgroup api Public API -+ * -+ * This is the public API for `libprotobuf-c`. These interfaces are stable and -+ * subject to Semantic Versioning guarantees. -+ * -+ * @{ -+ */ -+ -+/** -+ * Values for the `flags` word in `ProtobufCFieldDescriptor`. -+ */ -+typedef enum { -+ /** Set if the field is repeated and marked with the `packed` option. */ -+ PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0), -+ -+ /** Set if the field is marked with the `deprecated` option. */ -+ PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1), -+} ProtobufCFieldFlag; -+ -+/** -+ * Message field rules. -+ * -+ * \see [Defining A Message Type] in the Protocol Buffers documentation. -+ * -+ * [Defining A Message Type]: -+ * https://developers.google.com/protocol-buffers/docs/proto#simple -+ */ -+typedef enum { -+ /** A well-formed message must have exactly one of this field. */ -+ PROTOBUF_C_LABEL_REQUIRED, -+ -+ /** -+ * A well-formed message can have zero or one of this field (but not -+ * more than one). -+ */ -+ PROTOBUF_C_LABEL_OPTIONAL, -+ -+ /** -+ * This field can be repeated any number of times (including zero) in a -+ * well-formed message. The order of the repeated values will be -+ * preserved. -+ */ -+ PROTOBUF_C_LABEL_REPEATED, -+} ProtobufCLabel; -+ -+/** -+ * Field value types. -+ * -+ * \see [Scalar Value Types] in the Protocol Buffers documentation. -+ * -+ * [Scalar Value Types]: -+ * https://developers.google.com/protocol-buffers/docs/proto#scalar -+ */ -+typedef enum { -+ PROTOBUF_C_TYPE_INT32, /**< int32 */ -+ PROTOBUF_C_TYPE_SINT32, /**< signed int32 */ -+ PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */ -+ PROTOBUF_C_TYPE_INT64, /**< int64 */ -+ PROTOBUF_C_TYPE_SINT64, /**< signed int64 */ -+ PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */ -+ PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */ -+ PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */ -+ PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */ -+ PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */ -+ PROTOBUF_C_TYPE_FLOAT, /**< float */ -+ PROTOBUF_C_TYPE_DOUBLE, /**< double */ -+ PROTOBUF_C_TYPE_BOOL, /**< boolean */ -+ PROTOBUF_C_TYPE_ENUM, /**< enumerated type */ -+ PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */ -+ PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */ -+ PROTOBUF_C_TYPE_MESSAGE, /**< nested message */ -+} ProtobufCType; -+ -+/** -+ * Field wire types. -+ * -+ * \see [Message Structure] in the Protocol Buffers documentation. -+ * -+ * [Message Structure]: -+ * https://developers.google.com/protocol-buffers/docs/encoding#structure -+ */ -+typedef enum { -+ PROTOBUF_C_WIRE_TYPE_VARINT = 0, -+ PROTOBUF_C_WIRE_TYPE_64BIT = 1, -+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2, -+ /* "Start group" and "end group" wire types are unsupported. */ -+ PROTOBUF_C_WIRE_TYPE_32BIT = 5, -+} ProtobufCWireType; -+ -+struct ProtobufCAllocator; -+struct ProtobufCBinaryData; -+struct ProtobufCBuffer; -+struct ProtobufCBufferSimple; -+struct ProtobufCEnumDescriptor; -+struct ProtobufCEnumValue; -+struct ProtobufCEnumValueIndex; -+struct ProtobufCFieldDescriptor; -+struct ProtobufCIntRange; -+struct ProtobufCMessage; -+struct ProtobufCMessageDescriptor; -+struct ProtobufCMessageUnknownField; -+struct ProtobufCMethodDescriptor; -+struct ProtobufCService; -+struct ProtobufCServiceDescriptor; -+ -+typedef struct ProtobufCAllocator ProtobufCAllocator; -+typedef struct ProtobufCBinaryData ProtobufCBinaryData; -+typedef struct ProtobufCBuffer ProtobufCBuffer; -+typedef struct ProtobufCBufferSimple ProtobufCBufferSimple; -+typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor; -+typedef struct ProtobufCEnumValue ProtobufCEnumValue; -+typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex; -+typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor; -+typedef struct ProtobufCIntRange ProtobufCIntRange; -+typedef struct ProtobufCMessage ProtobufCMessage; -+typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor; -+typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField; -+typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor; -+typedef struct ProtobufCService ProtobufCService; -+typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor; -+ -+/** Boolean type. */ -+typedef int protobuf_c_boolean; -+ -+typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data); -+typedef void (*ProtobufCMessageInit)(ProtobufCMessage *); -+typedef void (*ProtobufCServiceDestroy)(ProtobufCService *); -+ -+/** -+ * Structure for defining a custom memory allocator. -+ */ -+struct ProtobufCAllocator { -+ /** Function to allocate memory. */ -+ void *(*alloc)(void *allocator_data, size_t size); -+ -+ /** Function to free memory. */ -+ void (*free)(void *allocator_data, void *pointer); -+ -+ /** Opaque pointer passed to `alloc` and `free` functions. */ -+ void *allocator_data; -+}; -+ -+/** -+ * Structure for the protobuf `bytes` scalar type. -+ * -+ * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of -+ * bytes. It may contain embedded `NUL` characters and is not required to be -+ * `NUL`-terminated. -+ */ -+struct ProtobufCBinaryData { -+ size_t len; /**< Number of bytes in the `data` field. */ -+ uint8_t *data; /**< Data bytes. */ -+}; -+ -+/** -+ * Structure for defining a virtual append-only buffer. Used by -+ * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized -+ * bytes. -+ * -+ * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to -+ * write to a `FILE` object: -+ * -+~~~{.c} -+typedef struct { -+ ProtobufCBuffer base; -+ FILE *fp; -+} BufferAppendToFile; -+ -+static void -+my_buffer_file_append(ProtobufCBuffer *buffer, -+ size_t len, -+ const uint8_t *data) -+{ -+ BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer; -+ fwrite(data, len, 1, file_buf->fp); // XXX: No error handling! -+} -+~~~ -+ * -+ * To use this new type of ProtobufCBuffer, it could be called as follows: -+ * -+~~~{.c} -+... -+BufferAppendToFile tmp = {0}; -+tmp.base.append = my_buffer_file_append; -+tmp.fp = fp; -+protobuf_c_message_pack_to_buffer(&message, &tmp); -+... -+~~~ -+ */ -+struct ProtobufCBuffer { -+ /** Append function. Consumes the `len` bytes stored at `data`. */ -+ void (*append)(ProtobufCBuffer *buffer, -+ size_t len, -+ const uint8_t *data); -+}; -+ -+/** -+ * Simple buffer "subclass" of `ProtobufCBuffer`. -+ * -+ * A `ProtobufCBufferSimple` object is declared on the stack and uses a -+ * scratch buffer provided by the user for the initial allocation. It performs -+ * exponential resizing, using dynamically allocated memory. A -+ * `ProtobufCBufferSimple` object can be created and used as follows: -+ * -+~~~{.c} -+uint8_t pad[128]; -+ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad); -+ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple; -+~~~ -+ * -+ * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a -+ * message has been serialized to a `ProtobufCBufferSimple` object, the -+ * serialized data bytes can be accessed from the `.data` field. -+ * -+ * To free the memory allocated by a `ProtobufCBufferSimple` object, if any, -+ * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example: -+ * -+~~~{.c} -+PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple); -+~~~ -+ * -+ * \see PROTOBUF_C_BUFFER_SIMPLE_INIT -+ * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR -+ */ -+struct ProtobufCBufferSimple { -+ /** "Base class". */ -+ ProtobufCBuffer base; -+ /** Number of bytes allocated in `data`. */ -+ size_t alloced; -+ /** Number of bytes currently stored in `data`. */ -+ size_t len; -+ /** Data bytes. */ -+ uint8_t *data; -+ /** Whether `data` must be freed. */ -+ protobuf_c_boolean must_free_data; -+ /** Allocator to use. May be NULL to indicate the system allocator. */ -+ ProtobufCAllocator *allocator; -+}; -+ -+/** -+ * Describes an enumeration as a whole, with all of its values. -+ */ -+struct ProtobufCEnumDescriptor { -+ /** Magic value checked to ensure that the API is used correctly. */ -+ uint32_t magic; -+ -+ /** The qualified name (e.g., "namespace.Type"). */ -+ const char *name; -+ /** The unqualified name as given in the .proto file (e.g., "Type"). */ -+ const char *short_name; -+ /** Identifier used in generated C code. */ -+ const char *c_name; -+ /** The dot-separated namespace. */ -+ const char *package_name; -+ -+ /** Number elements in `values`. */ -+ unsigned n_values; -+ /** Array of distinct values, sorted by numeric value. */ -+ const ProtobufCEnumValue *values; -+ -+ /** Number of elements in `values_by_name`. */ -+ unsigned n_value_names; -+ /** Array of named values, including aliases, sorted by name. */ -+ const ProtobufCEnumValueIndex *values_by_name; -+ -+ /** Number of elements in `value_ranges`. */ -+ unsigned n_value_ranges; -+ /** Value ranges, for faster lookups by numeric value. */ -+ const ProtobufCIntRange *value_ranges; -+ -+ /** Reserved for future use. */ -+ void *reserved1; -+ /** Reserved for future use. */ -+ void *reserved2; -+ /** Reserved for future use. */ -+ void *reserved3; -+ /** Reserved for future use. */ -+ void *reserved4; -+}; -+ -+/** -+ * Represents a single value of an enumeration. -+ */ -+struct ProtobufCEnumValue { -+ /** The string identifying this value in the .proto file. */ -+ const char *name; -+ -+ /** The string identifying this value in generated C code. */ -+ const char *c_name; -+ -+ /** The numeric value assigned in the .proto file. */ -+ int value; -+}; -+ -+/** -+ * Used by `ProtobufCEnumDescriptor` to look up enum values. -+ */ -+struct ProtobufCEnumValueIndex { -+ /** Name of the enum value. */ -+ const char *name; -+ /** Index into values[] array. */ -+ unsigned index; -+}; -+ -+/** -+ * Describes a single field in a message. -+ */ -+struct ProtobufCFieldDescriptor { -+ /** Name of the field as given in the .proto file. */ -+ const char *name; -+ -+ /** Tag value of the field as given in the .proto file. */ -+ uint32_t id; -+ -+ /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */ -+ ProtobufCLabel label; -+ -+ /** The type of the field. */ -+ ProtobufCType type; -+ -+ /** -+ * The offset in bytes of the message's C structure's quantifier field -+ * (the `has_MEMBER` field for optional members or the `n_MEMBER` field -+ * for repeated members. -+ */ -+ unsigned quantifier_offset; -+ -+ /** -+ * The offset in bytes into the message's C structure for the member -+ * itself. -+ */ -+ unsigned offset; -+ -+ /** -+ * A type-specific descriptor. -+ * -+ * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the -+ * corresponding `ProtobufCEnumDescriptor`. -+ * -+ * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to -+ * the corresponding `ProtobufCMessageDescriptor`. -+ * -+ * Otherwise this field is NULL. -+ */ -+ const void *descriptor; /* for MESSAGE and ENUM types */ -+ -+ /** The default value for this field, if defined. May be NULL. */ -+ const void *default_value; -+ -+ /** -+ * A flag word. Zero or more of the bits defined in the -+ * `ProtobufCFieldFlag` enum may be set. -+ */ -+ uint32_t flags; -+ -+ /** Reserved for future use. */ -+ unsigned reserved_flags; -+ /** Reserved for future use. */ -+ void *reserved2; -+ /** Reserved for future use. */ -+ void *reserved3; -+}; -+ -+/** -+ * Helper structure for optimizing int => index lookups in the case -+ * where the keys are mostly consecutive values, as they presumably are for -+ * enums and fields. -+ * -+ * The data structures requires that the values in the original array are -+ * sorted. -+ */ -+struct ProtobufCIntRange { -+ int start_value; -+ unsigned orig_index; -+ /* -+ * NOTE: the number of values in the range can be inferred by looking -+ * at the next element's orig_index. A dummy element is added to make -+ * this simple. -+ */ -+}; -+ -+/** -+ * An instance of a message. -+ * -+ * `ProtobufCMessage` is a light-weight "base class" for all messages. -+ * -+ * In particular, `ProtobufCMessage` doesn't have any allocation policy -+ * associated with it. That's because it's common to create `ProtobufCMessage` -+ * objects on the stack. In fact, that's what we recommend for sending messages. -+ * If the object is allocated from the stack, you can't really have a memory -+ * leak. -+ * -+ * This means that calls to functions like protobuf_c_message_unpack() which -+ * return a `ProtobufCMessage` must be paired with a call to a free function, -+ * like protobuf_c_message_free_unpacked(). -+ */ -+struct ProtobufCMessage { -+ /** The descriptor for this message type. */ -+ const ProtobufCMessageDescriptor *descriptor; -+ /** The number of elements in `unknown_fields`. */ -+ unsigned n_unknown_fields; -+ /** The fields that weren't recognized by the parser. */ -+ ProtobufCMessageUnknownField *unknown_fields; -+}; -+ -+/** -+ * Describes a message. -+ */ -+struct ProtobufCMessageDescriptor { -+ /** Magic value checked to ensure that the API is used correctly. */ -+ uint32_t magic; -+ -+ /** The qualified name (e.g., "namespace.Type"). */ -+ const char *name; -+ /** The unqualified name as given in the .proto file (e.g., "Type"). */ -+ const char *short_name; -+ /** Identifier used in generated C code. */ -+ const char *c_name; -+ /** The dot-separated namespace. */ -+ const char *package_name; -+ -+ /** -+ * Size in bytes of the C structure representing an instance of this -+ * type of message. -+ */ -+ size_t sizeof_message; -+ -+ /** Number of elements in `fields`. */ -+ unsigned n_fields; -+ /** Field descriptors, sorted by tag number. */ -+ const ProtobufCFieldDescriptor *fields; -+ /** Used for looking up fields by name. */ -+ const unsigned *fields_sorted_by_name; -+ -+ /** Number of elements in `field_ranges`. */ -+ unsigned n_field_ranges; -+ /** Used for looking up fields by id. */ -+ const ProtobufCIntRange *field_ranges; -+ -+ /** Message initialisation function. */ -+ ProtobufCMessageInit message_init; -+ -+ /** Reserved for future use. */ -+ void *reserved1; -+ /** Reserved for future use. */ -+ void *reserved2; -+ /** Reserved for future use. */ -+ void *reserved3; -+}; -+ -+/** -+ * An unknown message field. -+ */ -+struct ProtobufCMessageUnknownField { -+ /** The tag number. */ -+ uint32_t tag; -+ /** The wire type of the field. */ -+ ProtobufCWireType wire_type; -+ /** Number of bytes in `data`. */ -+ size_t len; -+ /** Field data. */ -+ uint8_t *data; -+}; -+ -+/** -+ * Method descriptor. -+ */ -+struct ProtobufCMethodDescriptor { -+ /** Method name. */ -+ const char *name; -+ /** Input message descriptor. */ -+ const ProtobufCMessageDescriptor *input; -+ /** Output message descriptor. */ -+ const ProtobufCMessageDescriptor *output; -+}; -+ -+/** -+ * Service. -+ */ -+struct ProtobufCService { -+ /** Service descriptor. */ -+ const ProtobufCServiceDescriptor *descriptor; -+ /** Function to invoke the service. */ -+ void (*invoke)(ProtobufCService *service, -+ unsigned method_index, -+ const ProtobufCMessage *input, -+ ProtobufCClosure closure, -+ void *closure_data); -+ /** Function to destroy the service. */ -+ void (*destroy)(ProtobufCService *service); -+}; -+ -+/** -+ * Service descriptor. -+ */ -+struct ProtobufCServiceDescriptor { -+ /** Magic value checked to ensure that the API is used correctly. */ -+ uint32_t magic; -+ -+ /** Service name. */ -+ const char *name; -+ /** Short version of service name. */ -+ const char *short_name; -+ /** C identifier for the service name. */ -+ const char *c_name; -+ /** Package name. */ -+ const char *package; -+ /** Number of elements in `methods`. */ -+ unsigned n_methods; -+ /** Method descriptors, in the order defined in the .proto file. */ -+ const ProtobufCMethodDescriptor *methods; -+ /** Sort index of methods. */ -+ const unsigned *method_indices_by_name; -+}; -+ -+/** -+ * Get the version of the protobuf-c library. Note that this is the version of -+ * the library linked against, not the version of the headers compiled against. -+ * -+ * \return A string containing the version number of protobuf-c. -+ */ -+PROTOBUF_C__API -+const char * -+protobuf_c_version(void); -+ -+/** -+ * Get the version of the protobuf-c library. Note that this is the version of -+ * the library linked against, not the version of the headers compiled against. -+ * -+ * \return A 32 bit unsigned integer containing the version number of -+ * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH. -+ */ -+PROTOBUF_C__API -+uint32_t -+protobuf_c_version_number(void); -+ -+/** -+ * The version of the protobuf-c headers, represented as a string using the same -+ * format as protobuf_c_version(). -+ */ -+#define PROTOBUF_C_VERSION "1.0.0" -+ -+/** -+ * The version of the protobuf-c headers, represented as an integer using the -+ * same format as protobuf_c_version_number(). -+ */ -+#define PROTOBUF_C_VERSION_NUMBER 1000000 -+ -+/** -+ * The minimum protoc-c version which works with the current version of the -+ * protobuf-c headers. -+ */ -+#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000 -+ -+/** -+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name. -+ * -+ * \param desc -+ * The `ProtobufCEnumDescriptor` object. -+ * \param name -+ * The `name` field from the corresponding `ProtobufCEnumValue` object to -+ * match. -+ * \return -+ * A `ProtobufCEnumValue` object. -+ * \retval NULL -+ * If not found. -+ */ -+PROTOBUF_C__API -+const ProtobufCEnumValue * -+protobuf_c_enum_descriptor_get_value_by_name( -+ const ProtobufCEnumDescriptor *desc, -+ const char *name); -+ -+/** -+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric -+ * value. -+ * -+ * \param desc -+ * The `ProtobufCEnumDescriptor` object. -+ * \param value -+ * The `value` field from the corresponding `ProtobufCEnumValue` object to -+ * match. -+ * -+ * \return -+ * A `ProtobufCEnumValue` object. -+ * \retval NULL -+ * If not found. -+ */ -+PROTOBUF_C__API -+const ProtobufCEnumValue * -+protobuf_c_enum_descriptor_get_value( -+ const ProtobufCEnumDescriptor *desc, -+ int value); -+ -+/** -+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by -+ * the name of the field. -+ * -+ * \param desc -+ * The `ProtobufCMessageDescriptor` object. -+ * \param name -+ * The name of the field. -+ * \return -+ * A `ProtobufCFieldDescriptor` object. -+ * \retval NULL -+ * If not found. -+ */ -+PROTOBUF_C__API -+const ProtobufCFieldDescriptor * -+protobuf_c_message_descriptor_get_field_by_name( -+ const ProtobufCMessageDescriptor *desc, -+ const char *name); -+ -+/** -+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by -+ * the tag value of the field. -+ * -+ * \param desc -+ * The `ProtobufCMessageDescriptor` object. -+ * \param value -+ * The tag value of the field. -+ * \return -+ * A `ProtobufCFieldDescriptor` object. -+ * \retval NULL -+ * If not found. -+ */ -+PROTOBUF_C__API -+const ProtobufCFieldDescriptor * -+protobuf_c_message_descriptor_get_field( -+ const ProtobufCMessageDescriptor *desc, -+ unsigned value); -+ -+/** -+ * Determine the number of bytes required to store the serialised message. -+ * -+ * \param message -+ * The message object to serialise. -+ * \return -+ * Number of bytes. -+ */ -+PROTOBUF_C__API -+size_t -+protobuf_c_message_get_packed_size(const ProtobufCMessage *message); -+ -+/** -+ * Serialise a message from its in-memory representation. -+ * -+ * This function stores the serialised bytes of the message in a pre-allocated -+ * buffer. -+ * -+ * \param message -+ * The message object to serialise. -+ * \param[out] out -+ * Buffer to store the bytes of the serialised message. This buffer must -+ * have enough space to store the packed message. Use -+ * protobuf_c_message_get_packed_size() to determine the number of bytes -+ * required. -+ * \return -+ * Number of bytes stored in `out`. -+ */ -+PROTOBUF_C__API -+size_t -+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out); -+ -+/** -+ * Serialise a message from its in-memory representation to a virtual buffer. -+ * -+ * This function calls the `append` method of a `ProtobufCBuffer` object to -+ * consume the bytes generated by the serialiser. -+ * -+ * \param message -+ * The message object to serialise. -+ * \param buffer -+ * The virtual buffer object. -+ * \return -+ * Number of bytes passed to the virtual buffer. -+ */ -+PROTOBUF_C__API -+size_t -+protobuf_c_message_pack_to_buffer( -+ const ProtobufCMessage *message, -+ ProtobufCBuffer *buffer); -+ -+/** -+ * Unpack a serialised message into an in-memory representation. -+ * -+ * \param descriptor -+ * The message descriptor. -+ * \param allocator -+ * `ProtobufCAllocator` to use for memory allocation. May be NULL to -+ * specify the default allocator. -+ * \param len -+ * Length in bytes of the serialised message. -+ * \param data -+ * Pointer to the serialised message. -+ * \return -+ * An unpacked message object. -+ * \retval NULL -+ * If an error occurred during unpacking. -+ */ -+PROTOBUF_C__API -+ProtobufCMessage * -+protobuf_c_message_unpack( -+ const ProtobufCMessageDescriptor *descriptor, -+ ProtobufCAllocator *allocator, -+ size_t len, -+ const uint8_t *data); -+ -+/** -+ * Free an unpacked message object. -+ * -+ * This function should be used to deallocate the memory used by a call to -+ * protobuf_c_message_unpack(). -+ * -+ * \param message -+ * The message object to free. -+ * \param allocator -+ * `ProtobufCAllocator` to use for memory deallocation. May be NULL to -+ * specify the default allocator. -+ */ -+PROTOBUF_C__API -+void -+protobuf_c_message_free_unpacked( -+ ProtobufCMessage *message, -+ ProtobufCAllocator *allocator); -+ -+/** -+ * Check the validity of a message object. -+ * -+ * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present. -+ * Recursively checks nested messages. -+ * -+ * \retval TRUE -+ * Message is valid. -+ * \retval FALSE -+ * Message is invalid. -+ */ -+PROTOBUF_C__API -+protobuf_c_boolean -+protobuf_c_message_check(const ProtobufCMessage *); -+ -+/** Message initialiser. */ -+#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL } -+ -+/** -+ * Initialise a message object from a message descriptor. -+ * -+ * \param descriptor -+ * Message descriptor. -+ * \param message -+ * Allocated block of memory of size `descriptor->sizeof_message`. -+ */ -+PROTOBUF_C__API -+void -+protobuf_c_message_init( -+ const ProtobufCMessageDescriptor *descriptor, -+ void *message); -+ -+/** -+ * Free a service. -+ * -+ * \param service -+ * The service object to free. -+ */ -+PROTOBUF_C__API -+void -+protobuf_c_service_destroy(ProtobufCService *service); -+ -+/** -+ * Look up a `ProtobufCMethodDescriptor` by name. -+ * -+ * \param desc -+ * Service descriptor. -+ * \param name -+ * Name of the method. -+ * -+ * \return -+ * A `ProtobufCMethodDescriptor` object. -+ * \retval NULL -+ * If not found. -+ */ -+PROTOBUF_C__API -+const ProtobufCMethodDescriptor * -+protobuf_c_service_descriptor_get_method_by_name( -+ const ProtobufCServiceDescriptor *desc, -+ const char *name); -+ -+/** -+ * Initialise a `ProtobufCBufferSimple` object. -+ */ -+#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \ -+{ \ -+ { protobuf_c_buffer_simple_append }, \ -+ sizeof(array_of_bytes), \ -+ 0, \ -+ (array_of_bytes), \ -+ 0, \ -+ NULL \ -+} -+ -+/** -+ * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory. -+ */ -+#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \ -+do { \ -+ if ((simp_buf)->must_free_data) { \ -+ if ((simp_buf)->allocator != NULL) \ -+ (simp_buf)->allocator->free( \ -+ (simp_buf)->allocator, \ -+ (simp_buf)->data); \ -+ else \ -+ free((simp_buf)->data); \ -+ } \ -+} while (0) -+ -+/** -+ * The `append` method for `ProtobufCBufferSimple`. -+ * -+ * \param buffer -+ * The buffer object to append to. Must actually be a -+ * `ProtobufCBufferSimple` object. -+ * \param len -+ * Number of bytes in `data`. -+ * \param data -+ * Data to append. -+ */ -+PROTOBUF_C__API -+void -+protobuf_c_buffer_simple_append( -+ ProtobufCBuffer *buffer, -+ size_t len, -+ const unsigned char *data); -+ -+PROTOBUF_C__API -+void -+protobuf_c_service_generated_init( -+ ProtobufCService *service, -+ const ProtobufCServiceDescriptor *descriptor, -+ ProtobufCServiceDestroy destroy); -+ -+PROTOBUF_C__API -+void -+protobuf_c_service_invoke_internal( -+ ProtobufCService *service, -+ unsigned method_index, -+ const ProtobufCMessage *input, -+ ProtobufCClosure closure, -+ void *closure_data); -+ -+/**@}*/ -+ -+PROTOBUF_C__END_DECLS -+ -+#endif /* PROTOBUF_C_H */ --- -2.0.0 -