diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2014-08-10 12:42:01 +0300 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2014-08-10 12:42:01 +0300 |
commit | a641e21b34aed824b6b919f7ab9937eaadf09473 (patch) | |
tree | cb7f5dbcc0043507e33f4443f860b76cec9c7553 /pb_decode.c | |
parent | 0150b98be60b1e123fa51c561a908c234b6379fe (diff) |
Separate field iterator logic from pb_decode to pb_common.
Diffstat (limited to 'pb_decode.c')
-rw-r--r-- | pb_decode.c | 140 |
1 files changed, 31 insertions, 109 deletions
diff --git a/pb_decode.c b/pb_decode.c index 4e187256..40da1aa4 100644 --- a/pb_decode.c +++ b/pb_decode.c @@ -15,36 +15,23 @@ #include "pb.h" #include "pb_decode.h" +#include "pb_common.h" /************************************** * Declarations internal to this file * **************************************/ -/* Iterator for pb_field_t list */ -typedef struct { - const pb_field_t *start; /* Start of the pb_field_t array */ - const pb_field_t *pos; /* Current position of the iterator */ - unsigned field_index; /* Zero-based index of the field. */ - unsigned required_field_index; /* Zero-based index that counts only the required fields */ - void *dest_struct; /* Pointer to the destination structure to decode to */ - void *pData; /* Pointer where to store current field value */ - void *pSize; /* Pointer where to store the size of current array field */ -} pb_field_iterator_t; - typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; static bool checkreturn buf_read(pb_istream_t *stream, uint8_t *buf, size_t count); static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, uint8_t *buf, size_t *size); -static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct); -static bool pb_field_next(pb_field_iterator_t *iter); -static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag); -static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter); -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter); -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_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); -static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iterator_t *iter); -static bool checkreturn find_extension_field(pb_field_iterator_t *iter); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); @@ -338,75 +325,11 @@ void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) #endif } -static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct) -{ - iter->start = iter->pos = fields; - iter->field_index = 0; - iter->required_field_index = 0; - iter->pData = (char*)dest_struct + iter->pos->data_offset; - iter->pSize = (char*)iter->pData + iter->pos->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->pos->data_size; - - if (PB_ATYPE(iter->pos->type) == PB_ATYPE_STATIC && - PB_HTYPE(iter->pos->type) == PB_HTYPE_REPEATED) - { - prev_size *= iter->pos->array_size; - } - else if (PB_ATYPE(iter->pos->type) == PB_ATYPE_POINTER) - { - prev_size = sizeof(void*); - } - - if (iter->pos->tag == 0) - return false; /* Only happens with empty message types */ - - if (PB_HTYPE(iter->pos->type) == PB_HTYPE_REQUIRED) - iter->required_field_index++; - - iter->pos++; - iter->field_index++; - if (iter->pos->tag == 0) - { - iter->pos = iter->start; - iter->field_index = 0; - iter->required_field_index = 0; - iter->pData = iter->dest_struct; - prev_size = 0; - notwrapped = false; - } - - iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; - iter->pSize = (char*)iter->pData + iter->pos->size_offset; - return notwrapped; -} - -static bool checkreturn pb_field_find(pb_field_iterator_t *iter, uint32_t tag) -{ - unsigned start = iter->field_index; - - do { - if (iter->pos->tag == tag && - PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) - { - return true; - } - (void)pb_field_next(iter); - } while (iter->field_index != start); - - return false; -} - /************************* * Decode a single field * *************************/ -static bool checkreturn decode_static_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_iter_t *iter) { pb_type_t type; pb_decoder_t func; @@ -504,7 +427,7 @@ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t } /* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ -static void initialize_pointer_field(void *pItem, pb_field_iterator_t *iter) +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) { if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) @@ -518,7 +441,7 @@ static void initialize_pointer_field(void *pItem, pb_field_iterator_t *iter) } #endif -static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { #ifndef PB_ENABLE_MALLOC UNUSED(wire_type); @@ -614,7 +537,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ #endif } -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { pb_callback_t *pCallback = (pb_callback_t*)iter->pData; @@ -661,7 +584,7 @@ static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type } } -static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter) +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { switch (PB_ATYPE(iter->pos->type)) { @@ -685,16 +608,15 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) { const pb_field_t *field = (const pb_field_t*)extension->type->arg; - pb_field_iterator_t iter; + pb_field_iter_t iter; if (field->tag != tag) return true; - iter.start = field; - iter.pos = field; - iter.field_index = 0; - iter.required_field_index = 0; - iter.dest_struct = extension->dest; + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + pb_field_iter_begin(&iter, field, extension->dest); iter.pData = extension->dest; iter.pSize = &extension->found; @@ -704,7 +626,7 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream, /* Try to decode an unknown field as an extension field. Tries each extension * decoder in turn, until one of them handles the field or loop ends. */ static bool checkreturn decode_extension(pb_istream_t *stream, - uint32_t tag, pb_wire_type_t wire_type, pb_field_iterator_t *iter) + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) { pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; size_t pos = stream->bytes_left; @@ -729,15 +651,15 @@ static bool checkreturn decode_extension(pb_istream_t *stream, /* Step through the iterator until an extension field is found or until all * entries have been checked. There can be only one extension field per * message. Returns false if no extension field is found. */ -static bool checkreturn find_extension_field(pb_field_iterator_t *iter) +static bool checkreturn find_extension_field(pb_field_iter_t *iter) { - unsigned start = iter->field_index; + const pb_field_t *start = iter->pos; do { if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) return true; - (void)pb_field_next(iter); - } while (iter->field_index != start); + (void)pb_field_iter_next(iter); + } while (iter->pos != start); return false; } @@ -745,8 +667,8 @@ static bool checkreturn find_extension_field(pb_field_iterator_t *iter) /* Initialize message fields to default values, recursively */ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) { - pb_field_iterator_t iter; - pb_field_init(&iter, fields, dest_struct); + pb_field_iter_t iter; + pb_field_iter_begin(&iter, fields, dest_struct); do { @@ -803,7 +725,7 @@ static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_str { /* Don't overwrite callback */ } - } while (pb_field_next(&iter)); + } while (pb_field_iter_next(&iter)); } /********************* @@ -814,9 +736,9 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[ { uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t extension_range_start = 0; - pb_field_iterator_t iter; + pb_field_iter_t iter; - pb_field_init(&iter, fields, dest_struct); + pb_field_iter_begin(&iter, fields, dest_struct); while (stream->bytes_left) { @@ -832,7 +754,7 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[ return false; } - if (!pb_field_find(&iter, tag)) + if (!pb_field_iter_find(&iter, tag)) { /* No match found, check if it matches an extension. */ if (tag >= extension_range_start) @@ -885,7 +807,7 @@ bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[ do { req_field_count = iter.required_field_index; last_type = iter.pos->type; - } while (pb_field_next(&iter)); + } while (pb_field_iter_next(&iter)); /* Fixup if last field was also required. */ if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) @@ -936,8 +858,8 @@ bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void * #ifdef PB_ENABLE_MALLOC void pb_release(const pb_field_t fields[], void *dest_struct) { - pb_field_iterator_t iter; - pb_field_init(&iter, fields, dest_struct); + pb_field_iter_t iter; + pb_field_iter_begin(&iter, fields, dest_struct); do { @@ -985,7 +907,7 @@ void pb_release(const pb_field_t fields[], void *dest_struct) pb_free(*(void**)iter.pData); *(void**)iter.pData = NULL; } - } while (pb_field_next(&iter)); + } while (pb_field_iter_next(&iter)); } #endif |