X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=pb_encode.c;h=30f60d83bcb7bea065f5b14d3d9bdc177e711bbb;hb=0161193cf97f46aa491501e665a75aa0afd9698d;hp=13bda22cca0abf0cbf7bf1e0f90b7bb98af4e70f;hpb=66a5f06c985537a7e45969c52260b083ec04e82b;p=apps%2Fagl-service-can-low-level.git diff --git a/pb_encode.c b/pb_encode.c index 13bda22c..30f60d83 100644 --- a/pb_encode.c +++ b/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 }; /******************************* @@ -59,11 +61,12 @@ static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) { + size_t i; pb_byte_t *dest = (pb_byte_t*)stream->state; stream->state = dest + count; - while (count--) - *dest++ = *buf++; + for (i = 0; i < count; i++) + dest[i] = buf[i]; return true; } @@ -201,32 +204,55 @@ 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) - { - const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; - return bytes->size == 0; - } - else if (PB_LTYPE(field->type) == PB_LTYPE_STRING) - { - return *(const char*)pData == '\0'; - } - else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED_LENGTH_BYTES) + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) { - /* 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; + if (PB_LTYPE(field->type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(field->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(field->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; + } } - else + { - /* 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++) { @@ -410,7 +436,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. */ @@ -425,7 +451,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 { @@ -693,9 +719,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) @@ -747,3 +770,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); +} +