de217699a07ca868103586d5342a5db2dff0c95f
[apps/agl-service-can-low-level.git] / pb_common.c
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 void 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
18 bool pb_field_iter_next(pb_field_iter_t *iter)
19 {
20     const pb_field_t *prev_field = iter->pos;
21
22     if (prev_field->tag == 0)
23     {
24         /* Handle empty message types, where the first field is already the terminator.
25          * In other cases, the iter->pos never points to the terminator. */
26         return false;
27     }
28     
29     iter->pos++;
30     
31     if (iter->pos->tag == 0)
32     {
33         /* Wrapped back to beginning, reinitialize */
34         pb_field_iter_begin(iter, iter->start, iter->dest_struct);
35         return false;
36     }
37     else
38     {
39         /* Increment the pointers based on previous field size */
40         size_t prev_size = prev_field->data_size;
41     
42         if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC &&
43             PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED)
44         {
45             /* In static arrays, the data_size tells the size of a single entry and
46              * array_size is the number of entries */
47             prev_size *= prev_field->array_size;
48         }
49         else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER)
50         {
51             /* Pointer fields always have a constant size in the main structure.
52              * The data_size only applies to the dynamically allocated area. */
53             prev_size = sizeof(void*);
54         }
55         
56         if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED)
57         {
58             /* Count the required fields, in order to check their presence in the
59              * decoder. */
60             iter->required_field_index++;
61         }
62     
63         iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset;
64         iter->pSize = (char*)iter->pData + iter->pos->size_offset;
65         return true;
66     }
67 }
68
69 bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
70 {
71     const pb_field_t *start = iter->pos;
72     
73     do {
74         if (iter->pos->tag == tag &&
75             PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION)
76         {
77             /* Found the wanted field */
78             return true;
79         }
80         
81         (void)pb_field_iter_next(iter);
82     } while (iter->pos != start);
83     
84     /* Searched all the way back to start, and found nothing. */
85     return false;
86 }
87
88