diff options
Diffstat (limited to 'pb_decode.c')
-rw-r--r-- | pb_decode.c | 164 |
1 files changed, 96 insertions, 68 deletions
diff --git a/pb_decode.c b/pb_decode.c index d4741130..bc6df7b9 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -303,8 +303,11 @@ 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) + if (PB_ATYPE(iter->current->type) == PB_ATYPE_STATIC && + PB_HTYPE(iter->current->type) == PB_HTYPE_REPEATED) + { prev_size *= iter->current->array_size; + } if (PB_HTYPE(iter->current->type) == PB_HTYPE_REQUIRED) iter->required_field_index++; @@ -343,11 +346,15 @@ static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag) * Decode a single field * *************************/ -static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) { - pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)]; + pb_type_t type; + pb_decoder_t func; - switch (PB_HTYPE(iter->current->type)) + type = iter->current->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) { case PB_HTYPE_REQUIRED: return func(stream, iter->current, iter->pData); @@ -356,9 +363,9 @@ static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_t *(bool*)iter->pSize = true; return func(stream, iter->current, iter->pData); - case PB_HTYPE_ARRAY: + case PB_HTYPE_REPEATED: if (wire_type == PB_WT_STRING - && PB_LTYPE(iter->current->type) <= PB_LTYPE_LAST_PACKABLE) + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) { /* Packed array */ bool status = true; @@ -395,48 +402,63 @@ static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_t (*size)++; return func(stream, iter->current, pItem); } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + + if (pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; - case PB_HTYPE_CALLBACK: + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) { - pb_callback_t *pCallback = (pb_callback_t*)iter->pData; - - if (pCallback->funcs.decode == NULL) - return pb_skip_field(stream, wire_type); - - if (wire_type == PB_WT_STRING) - { - pb_istream_t substream; - - if (!pb_make_string_substream(stream, &substream)) - return false; - - while (substream.bytes_left) - { - if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg)) - PB_RETURN_ERROR(stream, "callback failed"); - } - - pb_close_string_substream(stream, &substream); - return true; - } - else - { - /* Copy the single scalar value to stack. - * This is required so that we can limit the stream length, - * which in turn allows to use same callback for packed and - * not-packed fields. */ - pb_istream_t substream; - uint8_t buffer[10]; - size_t size = sizeof(buffer); - - if (!read_raw_value(stream, wire_type, buffer, &size)) - return false; - substream = pb_istream_from_buffer(buffer, size); - - return pCallback->funcs.decode(&substream, iter->current, pCallback->arg); - } + if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg)) + PB_RETURN_ERROR(stream, "callback failed"); } + pb_close_string_substream(stream, &substream); + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + uint8_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->current, pCallback->arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +{ + switch (PB_ATYPE(iter->current->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + default: PB_RETURN_ERROR(stream, "invalid field type"); } @@ -451,37 +473,43 @@ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_str /* Initialize size/has fields and apply default values */ do { + pb_type_t type; + type = iter.current->type; + if (iter.current->tag == 0) continue; - /* Initialize the size field for optional/repeated fields to 0. */ - if (PB_HTYPE(iter.current->type) == PB_HTYPE_OPTIONAL) - { - *(bool*)iter.pSize = false; - } - else if (PB_HTYPE(iter.current->type) == PB_HTYPE_ARRAY) + if (PB_ATYPE(type) == PB_ATYPE_STATIC) { - *(size_t*)iter.pSize = 0; - continue; /* Array is empty, no need to initialize contents */ + /* Initialize the size field for optional/repeated fields to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL) + { + *(bool*)iter.pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + *(size_t*)iter.pSize = 0; + continue; /* Array is empty, no need to initialize contents */ + } + + /* Initialize field contents to default value */ + if (PB_LTYPE(iter.current->type) == PB_LTYPE_SUBMESSAGE) + { + pb_message_set_to_defaults((const pb_field_t *) iter.current->ptr, iter.pData); + } + else if (iter.current->ptr != NULL) + { + memcpy(iter.pData, iter.current->ptr, iter.current->data_size); + } + else + { + memset(iter.pData, 0, iter.current->data_size); + } } - - /* Initialize field contents to default value */ - if (PB_HTYPE(iter.current->type) == PB_HTYPE_CALLBACK) + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) { continue; /* Don't overwrite callback */ } - else if (PB_LTYPE(iter.current->type) == PB_LTYPE_SUBMESSAGE) - { - pb_message_set_to_defaults((const pb_field_t *) iter.current->ptr, iter.pData); - } - else if (iter.current->ptr != NULL) - { - memcpy(iter.pData, iter.current->ptr, iter.current->data_size); - } - else - { - memset(iter.pData, 0, iter.current->data_size); - } } while (pb_field_next(&iter)); } @@ -715,7 +743,7 @@ bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field /* New array entries need to be initialized, while required and optional * submessages have already been initialized in the top-level pb_decode. */ - if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY) + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) status = pb_decode(&substream, submsg_fields, dest); else status = pb_decode_noinit(&substream, submsg_fields, dest); |