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