X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=pb_decode.c;h=2cde54c24d46591baa91224d1125971c9832c191;hb=7f53c3f7484679c1e38607f59542d43be1387650;hp=e2888f224079f6cc950bff4f7b0b2859699dc7bc;hpb=6dfba365b00175eae7e8b83aaf5d29ce190fd9eb;p=apps%2Fagl-service-can-low-level.git diff --git a/pb_decode.c b/pb_decode.c index e2888f22..2cde54c2 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -62,15 +62,15 @@ pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize) * Helper functions * ********************/ -bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +static bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) { uint64_t temp; - bool status = pb_decode_varint64(stream, &temp); + bool status = pb_decode_varint(stream, &temp); *dest = temp; return status; } -bool pb_decode_varint64(pb_istream_t *stream, uint64_t *dest) +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest) { uint8_t byte; int bitpos = 0; @@ -108,7 +108,7 @@ bool pb_skip_string(pb_istream_t *stream) return pb_read(stream, NULL, length); } -/* Currently all wire type related stuff is kept hidden from +/* Currently the wire type related stuff is kept hidden from * callbacks. They shouldn't need it. It's better for performance * to just assume the correct type and fail safely on corrupt message. */ @@ -185,13 +185,19 @@ static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, v { iter->start = iter->current = fields; iter->field_index = 0; - iter->pData = dest_struct; + iter->pData = dest_struct + iter->current->data_offset; + iter->pSize = (char*)iter->pData + iter->current->size_offset; iter->dest_struct = dest_struct; } static bool pb_field_next(pb_field_iterator_t *iter) { bool notwrapped = true; + size_t prev_size = iter->current->data_size; + + if (PB_HTYPE(iter->current->type) == PB_HTYPE_ARRAY) + prev_size *= iter->current->array_size; + iter->current++; iter->field_index++; if (iter->current->tag == 0) @@ -199,10 +205,11 @@ static bool pb_field_next(pb_field_iterator_t *iter) iter->current = iter->start; iter->field_index = 0; iter->pData = iter->dest_struct; + prev_size = 0; notwrapped = false; } - iter->pData = (char*)iter->pData + iter->current->data_offset; + iter->pData = (char*)iter->pData + prev_size + iter->current->data_offset; iter->pSize = (char*)iter->pData + iter->current->size_offset; return notwrapped; } @@ -224,7 +231,7 @@ static bool pb_field_find(pb_field_iterator_t *iter, int tag) * Decode a single field * *************************/ -bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter) +static bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter) { pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)]; @@ -269,9 +276,14 @@ bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter } case PB_HTYPE_CALLBACK: + { + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + + if (pCallback->funcs.decode == NULL) + return skip(stream, wire_type); + if (wire_type == PB_WT_STRING) { - pb_callback_t *pCallback = (pb_callback_t*)iter->pData; pb_istream_t substream; if (!make_string_substream(stream, &substream)) @@ -291,7 +303,6 @@ bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter * which in turn allows to use same callback for packed and * not-packed fields. */ pb_istream_t substream; - pb_callback_t *pCallback = (pb_callback_t*)iter->pData; uint8_t buffer[10]; size_t size = sizeof(buffer); @@ -301,7 +312,8 @@ bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter return pCallback->funcs.decode(&substream, iter->current, pCallback->arg); } - + } + default: return false; } @@ -342,6 +354,10 @@ bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struc { *(size_t*)iter.pSize = 0; } + else if (PB_HTYPE(iter.current->type) == PB_HTYPE_REQUIRED) + { + memset(iter.pData, 0, iter.current->data_size); + } } while (pb_field_next(&iter)); while (stream->bytes_left) @@ -349,7 +365,15 @@ bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struc uint32_t temp; int tag, wire_type; if (!pb_decode_varint32(stream, &temp)) - return stream->bytes_left == 0; /* Was it EOF? */ + { + if (stream->bytes_left == 0) + break; /* It was EOF */ + else + return false; /* It was error */ + } + + if (temp == 0) + break; /* Special feature: allow 0-terminated messages. */ tag = temp >> 3; wire_type = temp & 7; @@ -399,7 +423,7 @@ static void endian_copy(void *dest, void *src, size_t destsize, size_t srcsize) bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint64_t temp; - bool status = pb_decode_varint64(stream, &temp); + bool status = pb_decode_varint(stream, &temp); endian_copy(dest, &temp, field->data_size, sizeof(temp)); return status; } @@ -407,7 +431,7 @@ bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint64_t temp; - bool status = pb_decode_varint64(stream, &temp); + bool status = pb_decode_varint(stream, &temp); temp = (temp >> 1) ^ -(int64_t)(temp & 1); endian_copy(dest, &temp, field->data_size, sizeof(temp)); return status;