diff --git a/TODO b/TODO index 67e7be5..c0a7fb5 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,6 @@ - check over documentation again -- handle unknown fields when packing -- test code -- make services derive from ProtobufCService; - be usable with a cast. +- make services derive from ProtobufCService; be usable with a cast. - provide example rpc -- use size_t wherever appropriate in generated code, - and in uses of that code (eg pack and unpack) - To document: - __INIT macro diff --git a/src/google/protobuf-c/protobuf-c.c b/src/google/protobuf-c/protobuf-c.c index fd30f19..9afe844 100644 --- a/src/google/protobuf-c/protobuf-c.c +++ b/src/google/protobuf-c/protobuf-c.c @@ -7,7 +7,7 @@ #define PRINT_UNPACK_ERRORS 1 #if DO_LITTLE_ENDIAN_OPTIMIZATIONS -# if (__LITTLE_ENDIAN == __BYTE_ORDER) +# if (__LITTLE_ENDIAN == __uint8_t_ORDER) # define IS_LITTLE_ENDIAN 1 # else # define IS_LITTLE_ENDIAN 0 @@ -15,7 +15,7 @@ #endif -/* This file defines `__BYTE_ORDER' for the particular machine. */ +/* This file defines `__uint8_t_ORDER' for the particular machine. */ #include "protobuf-c.h" @@ -27,12 +27,11 @@ #define FREE(allocator, ptr) ((allocator)->free ((allocator)->allocator_data, (ptr))) #define UNALIGNED_ALLOC(allocator, size) ALLOC (allocator, size) /* placeholder */ #define STRUCT_MEMBER_P(struct_p, struct_offset) \ - ((void *) ((BYTE*) (struct_p) + (struct_offset))) + ((void *) ((uint8_t*) (struct_p) + (struct_offset))) #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \ ((member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) -typedef unsigned char BYTE; #define TRUE 1 #define FALSE 0 @@ -86,14 +85,14 @@ ProtobufCAllocator protobuf_c_system_allocator = void protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer, size_t len, - const unsigned char *data) + const uint8_t *data) { ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer; size_t new_len = simp->len + len; if (new_len > simp->alloced) { size_t new_alloced = simp->alloced * 2; - unsigned char *new_data; + uint8_t *new_data; while (new_alloced < new_len) new_alloced += new_alloced; new_data = ALLOC (&protobuf_c_default_allocator, new_alloced); @@ -239,7 +238,6 @@ required_field_get_packed_size (const ProtobufCFieldDescriptor *field, size_t len = strlen (*(char**) member); return rv + uint32_size (len) + len; } - case PROTOBUF_C_TYPE_BYTES: { size_t len = ((ProtobufCBinaryData*) member)->len; @@ -345,6 +343,13 @@ repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field, } return rv; } + +static inline size_t +unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field) +{ + return get_tag_size (field->tag) + field->len; +} + size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) { unsigned i; @@ -362,12 +367,14 @@ size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message) else rv += repeated_field_get_packed_size (field, * (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; } /* === pack() === */ static inline size_t -uint32_pack (uint32_t value, BYTE *out) +uint32_pack (uint32_t value, uint8_t *out) { unsigned rv = 0; if (value >= 0x80) @@ -395,7 +402,7 @@ uint32_pack (uint32_t value, BYTE *out) return rv; } static inline size_t -int32_pack (int32_t value, BYTE *out) +int32_pack (int32_t value, uint8_t *out) { if (value < 0) { @@ -411,12 +418,12 @@ int32_pack (int32_t value, BYTE *out) else return uint32_pack (value, out); } -static inline size_t sint32_pack (int32_t value, BYTE *out) +static inline size_t sint32_pack (int32_t value, uint8_t *out) { return uint32_pack (zigzag32 (value), out); } static size_t -uint64_pack (uint64_t value, BYTE *out) +uint64_pack (uint64_t value, uint8_t *out) { uint32_t hi = value>>32; uint32_t lo = value; @@ -446,11 +453,11 @@ uint64_pack (uint64_t value, BYTE *out) out[rv++] = hi; return rv; } -static inline size_t sint64_pack (int64_t value, BYTE *out) +static inline size_t sint64_pack (int64_t value, uint8_t *out) { return uint64_pack (zigzag64 (value), out); } -static inline size_t fixed32_pack (uint32_t value, BYTE *out) +static inline size_t fixed32_pack (uint32_t value, uint8_t *out) { #if IS_LITTLE_ENDIAN memcpy (out, &value, 4); @@ -462,7 +469,7 @@ static inline size_t fixed32_pack (uint32_t value, BYTE *out) #endif return 4; } -static inline size_t fixed64_pack (uint64_t value, BYTE *out) +static inline size_t fixed64_pack (uint64_t value, uint8_t *out) { #if IS_LITTLE_ENDIAN memcpy (out, &value, 8); @@ -472,19 +479,19 @@ static inline size_t fixed64_pack (uint64_t value, BYTE *out) #endif return 8; } -static inline size_t boolean_pack (protobuf_c_boolean value, BYTE *out) +static inline size_t boolean_pack (protobuf_c_boolean value, uint8_t *out) { *out = value ? 1 : 0; return 1; } -static inline size_t string_pack (const char * str, BYTE *out) +static inline size_t string_pack (const char * str, uint8_t *out) { size_t len = strlen (str); size_t rv = uint32_pack (len, out); memcpy (out + rv, str, len); return rv + len; } -static inline size_t binary_data_pack (const ProtobufCBinaryData *bd, BYTE *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); @@ -493,7 +500,7 @@ static inline size_t binary_data_pack (const ProtobufCBinaryData *bd, BYTE *out) } static inline size_t -prefixed_message_pack (const ProtobufCMessage *message, BYTE *out) +prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out) { size_t rv = protobuf_c_message_pack (message, out + 1); uint32_t rv_packed_size = uint32_size (rv); @@ -503,7 +510,7 @@ prefixed_message_pack (const ProtobufCMessage *message, BYTE *out) } /* wire-type will be added in required_field_pack() */ -static size_t tag_pack (uint32_t id, BYTE *out) +static size_t tag_pack (uint32_t id, uint8_t *out) { if (id < (1<<(32-3))) return uint32_pack (id<<3, out); @@ -513,7 +520,7 @@ static size_t tag_pack (uint32_t id, BYTE *out) static size_t required_field_pack (const ProtobufCFieldDescriptor *field, void *member, - BYTE *out) + uint8_t *out) { size_t rv = tag_pack (field->id, out); switch (field->type) @@ -575,7 +582,7 @@ static size_t optional_field_pack (const ProtobufCFieldDescriptor *field, const protobuf_c_boolean *has, void *member, - BYTE *out) + uint8_t *out) { if (field->type == PROTOBUF_C_TYPE_MESSAGE || field->type == PROTOBUF_C_TYPE_STRING) @@ -626,7 +633,7 @@ static size_t repeated_field_pack (const ProtobufCFieldDescriptor *field, size_t count, void *member, - BYTE *out) + uint8_t *out) { char *array = * (char **) member; size_t siz; @@ -641,8 +648,17 @@ repeated_field_pack (const ProtobufCFieldDescriptor *field, } 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, - unsigned char *out) + uint8_t *out) { unsigned i; size_t rv = 0; @@ -659,7 +675,8 @@ size_t protobuf_c_message_pack (const ProtobufCMessage *message, else rv += repeated_field_pack (field, * (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; } @@ -670,7 +687,7 @@ required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field, ProtobufCBuffer *buffer) { size_t rv; - BYTE scratch[MAX_UINT64_ENCODED_SIZE * 2]; + uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2]; rv = tag_pack (field->id, scratch); switch (field->type) { @@ -726,7 +743,7 @@ required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field, scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; rv += uint32_pack (sublen, scratch + rv); buffer->append (buffer, rv, scratch); - buffer->append (buffer, sublen, *(BYTE**)member); + buffer->append (buffer, sublen, *(uint8_t**)member); rv += sublen; break; } @@ -745,7 +762,7 @@ required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field, //PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED case PROTOBUF_C_TYPE_MESSAGE: { - BYTE simple_buffer_scratch[256]; + uint8_t simple_buffer_scratch[256]; size_t sublen; ProtobufCBufferSimple simple_buffer = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_buffer_scratch); @@ -804,6 +821,18 @@ repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field, 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) @@ -823,6 +852,8 @@ protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message, else rv += repeated_field_pack_to_buffer (field, * (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; } @@ -874,7 +905,7 @@ int_range_lookup (unsigned n_ranges, static size_t parse_tag_and_wiretype (size_t len, - const BYTE *data, + const uint8_t *data, uint32_t *tag_out, ProtobufCWireType *wiretype_out) { @@ -908,10 +939,10 @@ struct _ScannedMember { uint32_t tag; const ProtobufCFieldDescriptor *field; - BYTE wire_type; - BYTE length_prefix_len; + uint8_t wire_type; + uint8_t length_prefix_len; size_t len; - const unsigned char *data; + const uint8_t *data; }; #define MESSAGE_GET_UNKNOWNS(message) \ @@ -919,7 +950,7 @@ struct _ScannedMember (message), (message)->descriptor->unknown_field_array_offset) static inline uint32_t -scan_length_prefixed_data (size_t len, const BYTE *data, size_t *prefix_len_out) +scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out) { unsigned hdr_max = len < 5 ? len : 5; unsigned hdr_len; @@ -950,7 +981,7 @@ scan_length_prefixed_data (size_t len, const BYTE *data, size_t *prefix_len_out) } static inline uint32_t -parse_uint32 (unsigned len, const BYTE *data) +parse_uint32 (unsigned len, const uint8_t *data) { unsigned rv = data[0] & 0x7f; if (len > 1) @@ -970,7 +1001,7 @@ parse_uint32 (unsigned len, const BYTE *data) return rv; } static inline uint32_t -parse_int32 (unsigned len, const BYTE *data) +parse_int32 (unsigned len, const uint8_t *data) { return parse_uint32 (len, data); } @@ -983,7 +1014,7 @@ unzigzag32 (uint32_t v) return v>>1; } static inline uint32_t -parse_fixed_uint32 (const BYTE *data) +parse_fixed_uint32 (const uint8_t *data) { #if IS_LITTLE_ENDIAN uint32_t t; @@ -994,7 +1025,7 @@ parse_fixed_uint32 (const BYTE *data) #endif } static uint64_t -parse_uint64 (unsigned len, const BYTE *data) +parse_uint64 (unsigned len, const uint8_t *data) { unsigned shift, i; if (len < 5) @@ -1020,7 +1051,7 @@ unzigzag64 (uint64_t v) return v>>1; } static inline uint64_t -parse_fixed_uint64 (const BYTE *data) +parse_fixed_uint64 (const uint8_t *data) { #if IS_LITTLE_ENDIAN uint32_t t; @@ -1032,7 +1063,7 @@ parse_fixed_uint64 (const BYTE *data) #endif } static protobuf_c_boolean -parse_boolean (unsigned len, const BYTE *data) +parse_boolean (unsigned len, const uint8_t *data) { unsigned i; for (i = 0; i < len; i++) @@ -1047,7 +1078,7 @@ parse_required_member (ScannedMember *scanned_member, protobuf_c_boolean maybe_clear) { unsigned len = scanned_member->len; - const BYTE *data = scanned_member->data; + const uint8_t *data = scanned_member->data; ProtobufCWireType wire_type = scanned_member->wire_type; switch (scanned_member->field->type) { @@ -1221,11 +1252,11 @@ ProtobufCMessage * protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc, ProtobufCAllocator *allocator, size_t len, - const unsigned char *data) + const uint8_t *data) { ProtobufCMessage *rv; size_t rem = len; - const BYTE *at = data; + const uint8_t *at = data; const ProtobufCFieldDescriptor *last_field = desc->fields + 0; ScannedMember first_member_slab[16]; ScannedMember *scanned_member_slabs[30]; /* size of member i is (1<<(i+4)) */ diff --git a/src/google/protobuf-c/protobuf-c.h b/src/google/protobuf-c/protobuf-c.h index a20011d..12a1e49 100644 --- a/src/google/protobuf-c/protobuf-c.h +++ b/src/google/protobuf-c/protobuf-c.h @@ -5,6 +5,15 @@ #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 typedef enum { @@ -45,7 +54,7 @@ typedef struct _ProtobufCBinaryData ProtobufCBinaryData; struct _ProtobufCBinaryData { size_t len; - unsigned char *data; + uint8_t *data; }; typedef struct _ProtobufCIntRange ProtobufCIntRange; /* private */ @@ -71,7 +80,7 @@ struct _ProtobufCBuffer { void (*append)(ProtobufCBuffer *buffer, size_t len, - const unsigned char *data); + const uint8_t *data); }; /* --- enums --- */ typedef struct _ProtobufCEnumValue ProtobufCEnumValue; @@ -147,7 +156,7 @@ struct _ProtobufCMessage size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message); size_t protobuf_c_message_pack (const ProtobufCMessage *message, - unsigned char *out); + uint8_t *out); size_t protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message, ProtobufCBuffer *buffer); @@ -155,7 +164,7 @@ ProtobufCMessage * protobuf_c_message_unpack (const ProtobufCMessageDescriptor *, ProtobufCAllocator *allocator, size_t len, - const unsigned char *data); + const uint8_t *data); void protobuf_c_message_free_unpacked (ProtobufCMessage *message, ProtobufCAllocator *allocator); @@ -219,7 +228,7 @@ struct _ProtobufCMessageUnknownField uint32_t tag; ProtobufCWireType wire_type; size_t len; - unsigned char *data; + uint8_t *data; }; /* --- extra (superfluous) api: trivial buffer --- */ @@ -229,7 +238,7 @@ struct _ProtobufCBufferSimple ProtobufCBuffer base; size_t alloced; size_t len; - unsigned char *data; + uint8_t *data; protobuf_c_boolean must_free_data; }; #define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \ @@ -241,4 +250,7 @@ struct _ProtobufCBufferSimple /* ====== private ====== */ #include "protobuf-c-private.h" + +PROTOBUF_C_END_DECLS + #endif /* __PROTOBUF_C_RUNTIME_H_ */ diff --git a/src/google/protobuf/compiler/c/c_bytes_field.cc b/src/google/protobuf/compiler/c/c_bytes_field.cc index 7322699..763b131 100644 --- a/src/google/protobuf/compiler/c/c_bytes_field.cc +++ b/src/google/protobuf/compiler/c/c_bytes_field.cc @@ -61,7 +61,7 @@ void BytesFieldGenerator::GenerateStructMembers(io::Printer* printer) const printer->Print(variables_, "ProtobufCBinaryData $name$;\n"); break; case FieldDescriptor::LABEL_REPEATED: - printer->Print(variables_, "unsigned n_$name$;\n"); + printer->Print(variables_, "size_t n_$name$;\n"); printer->Print(variables_, "ProtobufCBinaryData *$name$;\n"); break; } diff --git a/src/google/protobuf/compiler/c/c_enum_field.cc b/src/google/protobuf/compiler/c/c_enum_field.cc index 9da7dce..7f2c159 100644 --- a/src/google/protobuf/compiler/c/c_enum_field.cc +++ b/src/google/protobuf/compiler/c/c_enum_field.cc @@ -66,7 +66,7 @@ void EnumFieldGenerator::GenerateStructMembers(io::Printer* printer) const printer->Print(variables_, "$type$ $name$;\n"); break; case FieldDescriptor::LABEL_REPEATED: - printer->Print(variables_, "unsigned n_$name$;\n"); + printer->Print(variables_, "size_t n_$name$;\n"); printer->Print(variables_, "$type$ *$name$;\n"); break; } diff --git a/src/google/protobuf/compiler/c/c_file.cc b/src/google/protobuf/compiler/c/c_file.cc index 8a13a25..529357c 100644 --- a/src/google/protobuf/compiler/c/c_file.cc +++ b/src/google/protobuf/compiler/c/c_file.cc @@ -84,6 +84,8 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#define PROTOBUF_C_$filename_identifier$__INCLUDED\n" "\n" "#include \n" + "\n" + "PROTOBUF_C_BEGIN_DECLS\n" "\n", "filename_identifier", filename_identifier); @@ -169,6 +171,8 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { } printer->Print( + "\n" + "PROTOBUF_C_END_DECLS\n" "\n\n#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", "filename_identifier", filename_identifier); } diff --git a/src/google/protobuf/compiler/c/c_message.cc b/src/google/protobuf/compiler/c/c_message.cc index 2a02409..c5de3bc 100644 --- a/src/google/protobuf/compiler/c/c_message.cc +++ b/src/google/protobuf/compiler/c/c_message.cc @@ -145,7 +145,7 @@ GenerateHelperFunctionDeclarations(io::Printer* printer) " (const $classname$ *message);\n" "size_t $lcclassname$__pack\n" " (const $classname$ *message,\n" - " unsigned char *out);\n" + " uint8_t *out);\n" "size_t $lcclassname$__pack_to_buffer\n" " (const $classname$ *message,\n" " ProtobufCBuffer *buffer);\n" @@ -153,7 +153,7 @@ GenerateHelperFunctionDeclarations(io::Printer* printer) " $lcclassname$__unpack\n" " (ProtobufCAllocator *allocator,\n" " size_t len,\n" - " const unsigned char *data);\n" + " const uint8_t *data);\n" "void $lcclassname$__free_unpacked\n" " ($classname$ *message,\n" " ProtobufCAllocator *allocator);\n" @@ -211,7 +211,7 @@ GenerateHelperFunctionDefinitions(io::Printer* printer) "}\n" "size_t $lcclassname$__pack\n" " (const $classname$ *message,\n" - " unsigned char *out)\n" + " uint8_t *out)\n" "{\n" " PROTOBUF_C_ASSERT (message->base.descriptor == &$lcclassname$__descriptor);\n" " return protobuf_c_message_pack ((ProtobufCMessage*)message, out);\n" @@ -227,7 +227,7 @@ GenerateHelperFunctionDefinitions(io::Printer* printer) " $lcclassname$__unpack\n" " (ProtobufCAllocator *allocator,\n" " size_t len,\n" - " const unsigned char *data)\n" + " const uint8_t *data)\n" "{\n" " return ($classname$ *)\n" " protobuf_c_message_unpack (&$lcclassname$__descriptor,\n" diff --git a/src/google/protobuf/compiler/c/c_message_field.cc b/src/google/protobuf/compiler/c/c_message_field.cc index 831822e..d9c4cd4 100644 --- a/src/google/protobuf/compiler/c/c_message_field.cc +++ b/src/google/protobuf/compiler/c/c_message_field.cc @@ -52,7 +52,7 @@ void MessageFieldGenerator::GenerateStructMembers(io::Printer* printer) const printer->Print(vars, "$type$ *$name$;\n"); break; case FieldDescriptor::LABEL_REPEATED: - printer->Print(vars, "unsigned n_$name$;\n"); + printer->Print(vars, "size_t n_$name$;\n"); printer->Print(vars, "$type$ **$name$;\n"); break; } diff --git a/src/google/protobuf/compiler/c/c_primitive_field.cc b/src/google/protobuf/compiler/c/c_primitive_field.cc index 9432369..3e73271 100644 --- a/src/google/protobuf/compiler/c/c_primitive_field.cc +++ b/src/google/protobuf/compiler/c/c_primitive_field.cc @@ -76,7 +76,7 @@ void PrimitiveFieldGenerator::GenerateStructMembers(io::Printer* printer) const printer->Print(vars, "$c_type$ $name$;\n"); break; case FieldDescriptor::LABEL_REPEATED: - printer->Print(vars, "unsigned n_$name$;\n"); + printer->Print(vars, "size_t n_$name$;\n"); printer->Print(vars, "$c_type$ *$name$;\n"); break; } diff --git a/src/google/protobuf/compiler/c/c_string_field.cc b/src/google/protobuf/compiler/c/c_string_field.cc index 890d513..3b0c65e 100644 --- a/src/google/protobuf/compiler/c/c_string_field.cc +++ b/src/google/protobuf/compiler/c/c_string_field.cc @@ -58,7 +58,7 @@ void StringFieldGenerator::GenerateStructMembers(io::Printer* printer) const printer->Print(variables_, "char *$name$;\n"); break; case FieldDescriptor::LABEL_REPEATED: - printer->Print(variables_, "unsigned n_$name$;\n"); + printer->Print(variables_, "size_t n_$name$;\n"); printer->Print(variables_, "char **$name$;\n"); break; } diff --git a/src/test/cxx-generate-packed-data.cc b/src/test/cxx-generate-packed-data.cc index 32a6977..4a3f446 100644 --- a/src/test/cxx-generate-packed-data.cc +++ b/src/test/cxx-generate-packed-data.cc @@ -752,6 +752,26 @@ static void dump_test_repeated_SubMess (void) dump_message_bytes(&mess, "test_repeated_submess_1"); } +static void dump_test_unknown_fields (void) +{ + EmptyMess mess; + google::protobuf::Message::Reflection *reflection = mess.GetReflection(); + google::protobuf::UnknownFieldSet *fs = reflection->MutableUnknownFields(); + google::protobuf::UnknownField *f; + f = fs->AddField(5454); + f->add_varint(255); + f = fs->AddField(5555); + f->add_fixed32(260); + dump_message_bytes (&mess, "test_unknown_fields_0"); + + fs->Clear(); + f = fs->AddField(6666); + f->add_length_delimited("xxxxxxxx"); + f = fs->AddField(7777); + f->add_fixed64(0x10101); + dump_message_bytes (&mess, "test_unknown_fields_1"); +} + int main() { dump_test_enum_small (); @@ -811,5 +831,6 @@ int main() dump_test_repeated_string (); dump_test_repeated_bytes (); dump_test_repeated_SubMess (); + dump_test_unknown_fields (); return 0; } diff --git a/src/test/test-full.proto b/src/test/test-full.proto index d0d0116..0a2b1f1 100644 --- a/src/test/test-full.proto +++ b/src/test/test-full.proto @@ -142,4 +142,6 @@ message TestMessRequiredBytes { message TestMessRequiredMessage { required SubMess test = 1; } +message EmptyMess { +} diff --git a/src/test/test-generated-code2.c b/src/test/test-generated-code2.c index ed3dc1d..cddaa34 100644 --- a/src/test/test-generated-code2.c +++ b/src/test/test-generated-code2.c @@ -975,6 +975,62 @@ static void test_repeated_SubMess (void) #undef DO_TEST } +static void test_unknown_fields (void) +{ + static Foo__EmptyMess mess = FOO__EMPTY_MESS__INIT; + static Foo__EmptyMess *mess2; + ProtobufCMessageUnknownField fields[2]; + size_t len; uint8_t *data; + + mess.base.n_unknown_fields = 2; + mess.base.unknown_fields = fields; + + fields[0].tag = 5454; + fields[0].wire_type = PROTOBUF_C_WIRE_TYPE_VARINT; + fields[0].len = 2; + fields[0].data = (uint8_t*)"\377\1"; + fields[1].tag = 5555; + fields[1].wire_type = PROTOBUF_C_WIRE_TYPE_32BIT; + fields[1].len = 4; + fields[1].data = (uint8_t*)"\4\1\0\0"; + mess2 = test_compare_pack_methods (&mess.base, &len, &data); + assert (mess2->base.n_unknown_fields == 2); + assert (mess2->base.unknown_fields[0].tag == 5454); + assert (mess2->base.unknown_fields[0].wire_type == PROTOBUF_C_WIRE_TYPE_VARINT); + assert (mess2->base.unknown_fields[0].len == 2); + assert (memcmp (mess2->base.unknown_fields[0].data, fields[0].data, 2) == 0); + assert (mess2->base.unknown_fields[1].tag == 5555); + assert (mess2->base.unknown_fields[1].wire_type == PROTOBUF_C_WIRE_TYPE_32BIT); + assert (mess2->base.unknown_fields[1].len == 4); + assert (memcmp (mess2->base.unknown_fields[1].data, fields[1].data, 4) == 0); + TEST_VERSUS_STATIC_ARRAY (len, data, test_unknown_fields_0); + free (data); + foo__empty_mess__free_unpacked (mess2, NULL); + + fields[0].tag = 6666; + fields[0].wire_type = PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED; + fields[0].len = 9; + fields[0].data = (uint8_t*)"\10xxxxxxxx"; + fields[1].tag = 7777; + fields[1].wire_type = PROTOBUF_C_WIRE_TYPE_64BIT; + fields[1].len = 8; + fields[1].data = (uint8_t*)"\1\1\1\0\0\0\0\0"; + mess2 = test_compare_pack_methods (&mess.base, &len, &data); + assert (mess2->base.n_unknown_fields == 2); + assert (mess2->base.unknown_fields[0].tag == 6666); + assert (mess2->base.unknown_fields[0].wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED); + assert (mess2->base.unknown_fields[0].len == 9); + assert (memcmp (mess2->base.unknown_fields[0].data, fields[0].data, 9) == 0); + assert (mess2->base.unknown_fields[1].tag == 7777); + assert (mess2->base.unknown_fields[1].wire_type == PROTOBUF_C_WIRE_TYPE_64BIT); + assert (mess2->base.unknown_fields[1].len == 8); + assert (memcmp (mess2->base.unknown_fields[1].data, fields[1].data, 8) == 0); + TEST_VERSUS_STATIC_ARRAY (len, data, test_unknown_fields_1); + free (data); + foo__empty_mess__free_unpacked (mess2, NULL); +} + + /* === simple testing framework === */ typedef void (*TestFunc) (void); @@ -1048,6 +1104,8 @@ static Test tests[] = { "test repeated string", test_repeated_string }, { "test repeated bytes", test_repeated_bytes }, { "test repeated SubMess", test_repeated_SubMess }, + + { "test unknown fields", test_unknown_fields } }; #define n_tests (sizeof(tests)/sizeof(Test))