From 27e0e60985937b69cf5396ee018665bbc0e0f6f3 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 20 Aug 2017 17:56:30 +0200 Subject: Sync nanopb --- car/pb_encode.c | 101 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 24 deletions(-) (limited to 'car/pb_encode.c') diff --git a/car/pb_encode.c b/car/pb_encode.c index cafe853..05d691d 100644 --- a/car/pb_encode.c +++ b/car/pb_encode.c @@ -27,6 +27,7 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); @@ -35,6 +36,7 @@ static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *f static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); /* --- Function pointers to field encoders --- * Order in the array must match pb_action_t LTYPE numbering. @@ -50,7 +52,7 @@ static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { &pb_enc_string, &pb_enc_submessage, NULL, /* extensions */ - &pb_enc_bytes /* PB_LTYPE_FIXED_LENGTH_BYTES */ + &pb_enc_fixed_length_bytes }; /******************************* @@ -202,32 +204,81 @@ static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *fie * This function implements the check for the zero value. */ static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) { - if(PB_LTYPE(field->type) == PB_LTYPE_BYTES) + pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { - const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; - return bytes->size == 0; + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)pSize == 0; } - else if (PB_LTYPE(field->type) == PB_LTYPE_STRING) + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { - return *(const char*)pData == '\0'; + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; } - else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED_LENGTH_BYTES) + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) { - /* Fixed length bytes is only empty if its length is fixed - * as 0. Which would be pretty strange, but we can check - * it anyway. */ - return field->data_size == 0; + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool*)pSize == false; } - else + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) + { + do + { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + { - /* PB_LTYPE_VARINT, UVARINT, SVARINT, FIXED32, FIXED64, - * SUBMESSAGE, EXTENSION: These all have integer or pointer - * value which can be compared with 0. This does the check - * byte-by-byte to avoid the switch-cast logic used in - * pb_enc_varint(). (Casting to char* is safe with regards - * to C strict aliasing rules.) + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. */ - uint_fast8_t i; + pb_size_t i; const char *p = (const char*)pData; for (i = 0; i < field->data_size; i++) { @@ -411,7 +462,7 @@ static bool checkreturn encode_extension_field(pb_ostream_t *stream, * Encode all fields * *********************/ -static void *remove_const(const void *p) +static void *pb_const_cast(const void *p) { /* Note: this casts away const, in order to use the common field iterator * logic for both encoding and decoding. */ @@ -426,7 +477,7 @@ static void *remove_const(const void *p) bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { pb_field_iter_t iter; - if (!pb_field_iter_begin(&iter, fields, remove_const(src_struct))) + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) return true; /* Empty message type */ do { @@ -694,9 +745,6 @@ static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *fie { const pb_bytes_array_t *bytes = NULL; - if (PB_LTYPE(field->type) == PB_LTYPE_FIXED_LENGTH_BYTES) - return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); - bytes = (const pb_bytes_array_t*)src; if (src == NULL) @@ -748,3 +796,8 @@ static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); } +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); +} + -- cgit v1.2.3