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