Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c.
2
 *
3
 * 2014 Petteri Aimonen <jpa@kapsi.fi>
4
 */
5
 
6
#include "pb_common.h"
7
 
8
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct)
9
{
10
    iter->start = fields;
11
    iter->pos = fields;
12
    iter->required_field_index = 0;
13
    iter->dest_struct = dest_struct;
14
    iter->pData = (char*)dest_struct + iter->pos->data_offset;
15
    iter->pSize = (char*)iter->pData + iter->pos->size_offset;
16
 
17
    return (iter->pos->tag != 0);
18
}
19
 
20
bool pb_field_iter_next(pb_field_iter_t *iter)
21
{
22
    const pb_field_t *prev_field = iter->pos;
23
 
24
    if (prev_field->tag == 0)
25
    {
26
        /* Handle empty message types, where the first field is already the terminator.
27
         * In other cases, the iter->pos never points to the terminator. */
28
        return false;
29
    }
30
 
31
    iter->pos++;
32
 
33
    if (iter->pos->tag == 0)
34
    {
35
        /* Wrapped back to beginning, reinitialize */
36
        (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct);
37
        return false;
38
    }
39
    else
40
    {
41
        /* Increment the pointers based on previous field size */
42
        size_t prev_size = prev_field->data_size;
43
 
44
        if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF &&
45
            PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF &&
46
            iter->pos->data_offset == PB_SIZE_MAX)
47
        {
48
            /* Don't advance pointers inside unions */
49
            return true;
50
        }
51
        else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC &&
52
                 PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED)
53
        {
54
            /* In static arrays, the data_size tells the size of a single entry and
55
             * array_size is the number of entries */
56
            prev_size *= prev_field->array_size;
57
        }
58
        else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER)
59
        {
60
            /* Pointer fields always have a constant size in the main structure.
61
             * The data_size only applies to the dynamically allocated area. */
62
            prev_size = sizeof(void*);
63
        }
64
 
65
        if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED)
66
        {
67
            /* Count the required fields, in order to check their presence in the
68
             * decoder. */
69
            iter->required_field_index++;
70
        }
71
 
72
        iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset;
73
        iter->pSize = (char*)iter->pData + iter->pos->size_offset;
74
        return true;
75
    }
76
}
77
 
78
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
79
{
80
    const pb_field_t *start = iter->pos;
81
 
82
    do {
83
        if (iter->pos->tag == tag &&
84
            PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION)
85
        {
86
            /* Found the wanted field */
87
            return true;
88
        }
89
 
90
        (void)pb_field_iter_next(iter);
91
    } while (iter->pos != start);
92
 
93
    /* Searched all the way back to start, and found nothing. */
94
    return false;
95
}
96
 
97