a9ae735075143db8c99a323258dba62a44eb40d2
[apps/agl-service-can-low-level.git] / pb_decode.c
1 /* pb_decode.c -- decode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6 #include "pb.h"
7 #include "pb_decode.h"
8 #include <string.h>
9
10 const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
11     (pb_decoder_t)&pb_dec_varint,
12     (pb_decoder_t)&pb_dec_svarint,
13     (pb_decoder_t)&pb_dec_fixed,
14     
15     (pb_decoder_t)&pb_dec_bytes,
16     (pb_decoder_t)&pb_dec_string,
17     (pb_decoder_t)&pb_dec_submessage
18 };
19
20 /**************
21  * pb_istream *
22  **************/
23
24 bool pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
25 {
26     bool status;
27     if (stream->bytes_left < count)
28         return false;
29     
30     status = stream->callback(stream, buf, count);
31     stream->bytes_left -= count;
32     return status;
33 }
34
35 static bool buf_read(pb_istream_t *stream, uint8_t *buf, size_t count)
36 {
37     uint8_t *source = (uint8_t*)stream->state;
38     
39     if (buf != NULL)
40         memcpy(buf, source, count);
41     
42     stream->state = source + count;
43     return true;
44 }
45
46 pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
47 {
48     pb_istream_t stream;
49     stream.callback = &buf_read;
50     stream.state = buf;
51     stream.bytes_left = bufsize;
52     return stream;
53 }
54
55 /********************
56  * Helper functions *
57  ********************/
58
59 bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
60 {
61     uint64_t temp;
62     bool status = pb_decode_varint64(stream, &temp);
63     *dest = temp;
64     return status;
65 }
66
67 bool pb_decode_varint64(pb_istream_t *stream, uint64_t *dest)
68 {
69     uint8_t byte;
70     int bitpos = 0;
71     *dest = 0;
72     
73     while (bitpos < 64 && pb_read(stream, &byte, 1))
74     {
75         *dest |= (byte & 0x7F) << bitpos;
76         bitpos += 7;
77         
78         if (!(byte & 0x80))
79             return true;
80     }
81     
82     return false;
83 }
84
85 bool pb_skip_varint(pb_istream_t *stream)
86 {
87     uint8_t byte;
88     do
89     {
90         if (!pb_read(stream, &byte, 1))
91             return false;
92     } while (byte & 0x80);
93     return true;
94 }
95
96 bool pb_skip_string(pb_istream_t *stream)
97 {
98     uint32_t length;
99     if (!pb_decode_varint32(stream, &length))
100         return false;
101     
102     return pb_read(stream, NULL, length);
103 }
104
105 /* Currently all wire type related stuff is kept hidden from
106  * callbacks. They shouldn't need it. It's better for performance
107  * to just assume the correct type and fail safely on corrupt message.
108  */
109
110 enum wire_type_t {
111     WT_VARINT = 0,
112     WT_64BIT  = 1,
113     WT_STRING = 2,
114     WT_32BIT  = 5
115 };
116
117 static bool skip(pb_istream_t *stream, int wire_type)
118 {
119     switch (wire_type)
120     {
121         case WT_VARINT: return pb_skip_varint(stream);
122         case WT_64BIT: return pb_read(stream, NULL, 8);
123         case WT_STRING: return pb_skip_string(stream);
124         case WT_32BIT: return pb_read(stream, NULL, 4);
125         default: return false;
126     }
127 }
128
129 /* Read a raw value to buffer, for the purpose of passing it to callback.
130  * Size is maximum size on call, and actual size on return. */
131 static bool read_raw_value(pb_istream_t *stream, int wire_type, uint8_t *buf, size_t *size)
132 {
133     size_t max_size = *size;
134     switch (wire_type)
135     {
136         case WT_VARINT:
137             *size = 0;
138             do
139             {
140                 (*size)++;
141                 if (*size > max_size) return false;
142                 if (!pb_read(stream, buf, 1)) return false;
143             } while (*buf++ & 0x80);
144             return true;
145             
146         case WT_64BIT:
147             *size = 8;
148             return pb_read(stream, buf, 8);
149         
150         case WT_32BIT:
151             *size = 4;
152             return pb_read(stream, buf, 4);
153         
154         default: return false;
155     }
156 }
157
158 /* Decode string length from stream and return a substream with limited length */
159 static bool make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
160 {
161     uint32_t size;
162     if (!pb_decode_varint32(stream, &size))
163         return false;
164     
165     *substream = *stream;
166     if (substream->bytes_left < size)
167         return false;
168     
169     substream->bytes_left = size;
170     stream->bytes_left -= size;
171     return true;
172 }
173
174 bool decode_field(pb_istream_t *stream, int wire_type, const pb_field_t *field, void *dest_struct)
175 {
176     pb_decoder_t func = PB_DECODERS[PB_LTYPE(field->type)];
177     void *pData = (char*)dest_struct + field->data_offset;
178     void *pSize = (char*)dest_struct + field->size_offset;
179     
180     switch (PB_HTYPE(field->type))
181     {
182         case PB_HTYPE_REQUIRED:
183             return func(stream, field, pData);
184             
185         case PB_HTYPE_OPTIONAL:
186             *(bool*)pSize = true;
187             return func(stream, field, pData);
188     
189         case PB_HTYPE_ARRAY:
190             if (wire_type == WT_STRING
191                 && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
192             {
193                 /* Packed array */
194                 size_t *size = (size_t*)pSize;
195                 pb_istream_t substream;
196                 if (!make_string_substream(stream, &substream))
197                     return false;
198                 
199                 while (substream.bytes_left && *size < field->array_size)
200                 {
201                     void *pItem = (uint8_t*)pData + field->data_size * (*size);
202                     if (!func(stream, field, pItem))
203                         return false;
204                     (*size)++;
205                 }
206                 return (substream.bytes_left == 0);
207             }
208             else
209             {
210                 /* Repeated field */
211                 size_t *size = (size_t*)pSize;
212                 void *pItem = (uint8_t*)pData + field->data_size * (*size);
213                 if (*size >= field->array_size)
214                     return false;
215                 
216                 (*size)++;
217                 return func(stream, field, pItem);
218             }
219         
220         case PB_HTYPE_CALLBACK:
221             if (wire_type == WT_STRING)
222             {
223                 pb_callback_t *pCallback = (pb_callback_t*)pData;
224                 pb_istream_t substream;
225                 
226                 if (!make_string_substream(stream, &substream))
227                     return false;
228                 
229                 while (substream.bytes_left)
230                 {
231                     if (!pCallback->funcs.decode(&substream, field, pCallback->arg))
232                         return false;
233                 }
234                 return true;
235             }
236             else
237             {
238                 /* Copy the single scalar value to stack.
239                  * This is required so that we can limit the stream length,
240                  * which in turn allows to use same callback for packed and
241                  * not-packed fields. */
242                 pb_istream_t substream;
243                 pb_callback_t *pCallback = (pb_callback_t*)pData;
244                 uint8_t buffer[10];
245                 size_t size = sizeof(buffer);
246                 
247                 if (!read_raw_value(stream, wire_type, buffer, &size))
248                     return false;
249                 substream = pb_istream_from_buffer(buffer, size);
250                 
251                 return pCallback->funcs.decode(&substream, field, pCallback->arg);
252             }
253             
254         default:
255             return false;
256     }
257 }
258
259 bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
260 {
261     /* Used to check for required fields */
262     uint32_t fields_seen = 0;
263     int i;
264     
265     /* Initialize size/has fields and apply default values */
266     for (i = 0; fields[i].tag != 0; i++)
267     {
268         void *pData = (char*)dest_struct + fields[i].data_offset;
269         void *pSize = (char*)dest_struct + fields[i].size_offset;
270         if (PB_HTYPE(fields[i].type) == PB_HTYPE_OPTIONAL)
271         {
272             *(bool*)pSize = false;
273             
274             /* Initialize to default value */
275             if (fields[i].ptr != NULL)
276                 memcpy(pData, fields[i].ptr, fields[i].data_size);
277             else
278                 memset(pData, 0, fields[i].data_size);
279         }
280         else if (PB_HTYPE(fields[i].type) == PB_HTYPE_ARRAY)
281         {
282             *(size_t*)pSize = 0;
283         }
284     }
285     
286     while (stream->bytes_left)
287     {
288         uint32_t temp;
289         int tag, wire_type;
290         if (!pb_decode_varint32(stream, &temp))
291             return false;
292         
293         tag = temp >> 3;
294         wire_type = temp & 7;
295         
296         i = 0;
297         while (fields[i].tag != 0 && fields[i].tag != tag)
298         {
299             i++;
300         }
301         
302         if (fields[i].tag == 0) /* No match found, skip data */
303         {
304             skip(stream, wire_type);
305             continue;
306         }
307         
308         fields_seen |= 1 << (i & 31);
309             
310         if (!decode_field(stream, wire_type, &fields[i], dest_struct))
311             return false;
312     }
313     
314     /* Check that all required fields (mod 31) were present. */
315     for (i = 0; fields[i].tag != 0; i++)
316     {
317         if (PB_HTYPE(fields[i].type) == PB_HTYPE_REQUIRED &&
318             !(fields_seen & (1 << (i & 31))))
319         {
320             return false;
321         }
322     }
323     
324     return true;
325 }
326
327 /* Field decoders */
328
329 /* Copy destsize bytes from src so that values are casted properly.
330  * On little endian machine, copy first n bytes of src
331  * On big endian machine, copy last n bytes of src
332  * srcsize must always be larger than destsize
333  */
334 static void endian_copy(void *dest, void *src, size_t destsize, size_t srcsize)
335 {
336 #ifdef __BIG_ENDIAN__
337     memcpy(dest, (char*)src + (srcsize - destsize), destsize);
338 #else
339     memcpy(dest, src, destsize);
340 #endif
341 }
342
343 bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
344 {
345     uint64_t temp;
346     bool status = pb_decode_varint64(stream, &temp);
347     endian_copy(dest, &temp, field->data_size, sizeof(temp));
348     return status;
349 }
350
351 bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
352 {
353     uint64_t temp;
354     bool status = pb_decode_varint64(stream, &temp);
355     temp = (temp >> 1) ^ -(int64_t)(temp & 1);
356     endian_copy(dest, &temp, field->data_size, sizeof(temp));
357     return status;
358 }
359
360 bool pb_dec_fixed(pb_istream_t *stream, const pb_field_t *field, void *dest)
361 {
362     uint8_t bytes[8] = {0};
363     bool status = pb_read(stream, bytes, field->data_size);
364     
365 #ifdef __BIG_ENDIAN__
366     uint8_t lebytes[8] = {bytes[7], bytes[6], bytes[5], bytes[4], 
367                           bytes[3], bytes[2], bytes[1], bytes[0]};
368     endian_copy(dest, lebytes, field->data_size, 8);
369 #else
370     endian_copy(dest, bytes, field->data_size, 8);
371 #endif
372     return status;
373 }
374
375 bool pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
376 {
377     pb_bytes_array_t *x = (pb_bytes_array_t*)dest;
378     
379     uint32_t temp;
380     if (!pb_decode_varint32(stream, &temp))
381         return false;
382     x->size = temp;
383     
384     /* Note: data_size includes the size of the x.size field, too.
385      * Calculate actual size starting from offset. */
386     if (x->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
387         return false;
388     
389     return pb_read(stream, x->bytes, x->size);
390 }
391
392 bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
393 {
394     uint32_t size;
395     bool status;
396     if (!pb_decode_varint32(stream, &size))
397         return false;
398     
399     if (size > field->data_size - 1)
400         return false;
401     
402     status = pb_read(stream, (uint8_t*)dest, size);
403     *((uint8_t*)dest + size) = 0;
404     return status;
405 }
406
407 bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
408 {
409     pb_istream_t substream;
410     
411     if (!make_string_substream(stream, &substream))
412         return false;
413     
414     if (field->ptr == NULL)
415         return false;
416     
417     return pb_decode(&substream, (pb_field_t*)field->ptr, dest);
418 }