Declare static functions before use.
[apps/agl-service-can-low-level.git] / pb_encode.c
1 /* pb_encode.c -- encode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6 #define NANOPB_INTERNALS
7 #include "pb.h"
8 #include "pb_encode.h"
9
10 /* Use the GCC warn_unused_result attribute to check that all return values
11  * are propagated correctly. On other compilers and gcc before 3.4.0 just
12  * ignore the annotation.
13  */
14 #if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
15     #define checkreturn
16 #else
17     #define checkreturn __attribute__((warn_unused_result))
18 #endif
19
20 /**************************************
21  * Declarations internal to this file *
22  **************************************/
23 typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
24
25 static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count);
26 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func);
27 static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
28 static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
29 static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
30
31
32 /* --- Function pointers to field encoders ---
33  * Order in the array must match pb_action_t LTYPE numbering.
34  */
35 static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
36     &pb_enc_varint,
37     &pb_enc_svarint,
38     &pb_enc_fixed32,
39     &pb_enc_fixed64,
40     
41     &pb_enc_bytes,
42     &pb_enc_string,
43     &pb_enc_submessage,
44     NULL /* extensions */
45 };
46
47 /*******************************
48  * pb_ostream_t implementation *
49  *******************************/
50
51 static bool checkreturn buf_write(pb_ostream_t *stream, const uint8_t *buf, size_t count)
52 {
53     uint8_t *dest = (uint8_t*)stream->state;
54     stream->state = dest + count;
55     
56     while (count--)
57         *dest++ = *buf++;
58     
59     return true;
60 }
61
62 pb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize)
63 {
64     pb_ostream_t stream;
65 #ifdef PB_BUFFER_ONLY
66     stream.callback = (void*)1; /* Just a marker value */
67 #else
68     stream.callback = &buf_write;
69 #endif
70     stream.state = buf;
71     stream.max_size = bufsize;
72     stream.bytes_written = 0;
73 #ifndef PB_NO_ERRMSG
74     stream.errmsg = NULL;
75 #endif
76     return stream;
77 }
78
79 bool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count)
80 {
81     if (stream->callback != NULL)
82     {
83         if (stream->bytes_written + count > stream->max_size)
84             PB_RETURN_ERROR(stream, "stream full");
85
86 #ifdef PB_BUFFER_ONLY
87         if (!buf_write(stream, buf, count))
88             PB_RETURN_ERROR(stream, "io error");
89 #else        
90         if (!stream->callback(stream, buf, count))
91             PB_RETURN_ERROR(stream, "io error");
92 #endif
93     }
94     
95     stream->bytes_written += count;
96     return true;
97 }
98
99 /*************************
100  * Encode a single field *
101  *************************/
102
103 /* Encode a static array. Handles the size calculations and possible packing. */
104 static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
105                          const void *pData, size_t count, pb_encoder_t func)
106 {
107     size_t i;
108     const void *p;
109     size_t size;
110     
111     if (count == 0)
112         return true;
113         
114     if (count > field->array_size)
115         PB_RETURN_ERROR(stream, "array max size exceeded");
116     
117     /* We always pack arrays if the datatype allows it. */
118     if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
119     {
120         if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
121             return false;
122         
123         /* Determine the total size of packed array. */
124         if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
125         {
126             size = 4 * count;
127         }
128         else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
129         {
130             size = 8 * count;
131         }
132         else
133         { 
134             pb_ostream_t sizestream = PB_OSTREAM_SIZING;
135             p = pData;
136             for (i = 0; i < count; i++)
137             {
138                 if (!func(&sizestream, field, p))
139                     return false;
140                 p = (const char*)p + field->data_size;
141             }
142             size = sizestream.bytes_written;
143         }
144         
145         if (!pb_encode_varint(stream, (uint64_t)size))
146             return false;
147         
148         if (stream->callback == NULL)
149             return pb_write(stream, NULL, size); /* Just sizing.. */
150         
151         /* Write the data */
152         p = pData;
153         for (i = 0; i < count; i++)
154         {
155             if (!func(stream, field, p))
156                 return false;
157             p = (const char*)p + field->data_size;
158         }
159     }
160     else
161     {
162         p = pData;
163         for (i = 0; i < count; i++)
164         {
165             if (!pb_encode_tag_for_field(stream, field))
166                 return false;
167             if (!func(stream, field, p))
168                 return false;
169             p = (const char*)p + field->data_size;
170         }
171     }
172     
173     return true;
174 }
175
176 /* Encode a field with static allocation, i.e. one whose data is stored
177  * in the structure itself. */
178 static bool checkreturn encode_static_field(pb_ostream_t *stream,
179     const pb_field_t *field, const void *pData)
180 {
181     pb_encoder_t func;
182     const void *pSize;
183     bool dummy = true;
184     
185     func = PB_ENCODERS[PB_LTYPE(field->type)];
186     
187     if (field->size_offset)
188         pSize = (const char*)pData + field->size_offset;
189     else
190         pSize = &dummy;
191     
192     switch (PB_HTYPE(field->type))
193     {
194         case PB_HTYPE_REQUIRED:
195             if (!pb_encode_tag_for_field(stream, field))
196                 return false;
197             if (!func(stream, field, pData))
198                 return false;
199             break;
200         
201         case PB_HTYPE_OPTIONAL:
202             if (*(const bool*)pSize)
203             {
204                 if (!pb_encode_tag_for_field(stream, field))
205                     return false;
206             
207                 if (!func(stream, field, pData))
208                     return false;
209             }
210             break;
211         
212         case PB_HTYPE_REPEATED:
213             if (!encode_array(stream, field, pData, *(const size_t*)pSize, func))
214                 return false;
215             break;
216         
217         default:
218             PB_RETURN_ERROR(stream, "invalid field type");
219     }
220     
221     return true;
222 }
223
224 /* Encode a field with callback semantics. This means that a user function is
225  * called to provide and encode the actual data. */
226 static bool checkreturn encode_callback_field(pb_ostream_t *stream,
227     const pb_field_t *field, const void *pData)
228 {
229     const pb_callback_t *callback = (const pb_callback_t*)pData;
230     
231 #ifdef PB_OLD_CALLBACK_STYLE
232     const void *arg = callback->arg;
233 #else
234     void * const *arg = &(callback->arg);
235 #endif    
236     
237     if (callback->funcs.encode != NULL)
238     {
239         if (!callback->funcs.encode(stream, field, arg))
240             PB_RETURN_ERROR(stream, "callback error");
241     }
242     return true;
243 }
244
245 /* Encode a single field of any callback or static type. */
246 static bool checkreturn encode_field(pb_ostream_t *stream,
247     const pb_field_t *field, const void *pData)
248 {
249     switch (PB_ATYPE(field->type))
250     {
251         case PB_ATYPE_STATIC:
252             return encode_static_field(stream, field, pData);
253         
254         case PB_ATYPE_CALLBACK:
255             return encode_callback_field(stream, field, pData);
256         
257         default:
258             PB_RETURN_ERROR(stream, "invalid field type");
259     }
260 }
261
262 /* Default handler for extension fields. Expects to have a pb_field_t
263  * pointer in the extension->type->arg field. */
264 static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
265     const pb_extension_t *extension)
266 {
267     const pb_field_t *field = (const pb_field_t*)extension->type->arg;
268     return encode_field(stream, field, extension->dest);
269 }
270
271 /* Walk through all the registered extensions and give them a chance
272  * to encode themselves. */
273 static bool checkreturn encode_extension_field(pb_ostream_t *stream,
274     const pb_field_t *field, const void *pData)
275 {
276     const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
277     UNUSED(field);
278     
279     while (extension)
280     {
281         bool status;
282         if (extension->type->encode)
283             status = extension->type->encode(stream, extension);
284         else
285             status = default_extension_encoder(stream, extension);
286
287         if (!status)
288             return false;
289         
290         extension = extension->next;
291     }
292     
293     return true;
294 }
295
296 /*********************
297  * Encode all fields *
298  *********************/
299
300 bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
301 {
302     const pb_field_t *field = fields;
303     const void *pData = src_struct;
304     size_t prev_size = 0;
305     
306     while (field->tag != 0)
307     {
308         pData = (const char*)pData + prev_size + field->data_offset;
309         prev_size = field->data_size;
310         
311         /* Special case for static arrays */
312         if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
313             PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
314         {
315             prev_size *= field->array_size;
316         }
317         
318         if (PB_LTYPE(field->type) == PB_LTYPE_EXTENSION)
319         {
320             /* Special case for the extension field placeholder */
321             if (!encode_extension_field(stream, field, pData))
322                 return false;
323         }
324         else
325         {
326             /* Regular field */
327             if (!encode_field(stream, field, pData))
328                 return false;
329         }
330     
331         field++;
332     }
333     
334     return true;
335 }
336
337 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
338 {
339     return pb_encode_submessage(stream, fields, src_struct);
340 }
341
342 /********************
343  * Helper functions *
344  ********************/
345 bool checkreturn pb_encode_varint(pb_ostream_t *stream, uint64_t value)
346 {
347     uint8_t buffer[10];
348     size_t i = 0;
349     
350     if (value == 0)
351         return pb_write(stream, (uint8_t*)&value, 1);
352     
353     while (value)
354     {
355         buffer[i] = (uint8_t)((value & 0x7F) | 0x80);
356         value >>= 7;
357         i++;
358     }
359     buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
360     
361     return pb_write(stream, buffer, i);
362 }
363
364 bool checkreturn pb_encode_svarint(pb_ostream_t *stream, int64_t value)
365 {
366     uint64_t zigzagged;
367     if (value < 0)
368         zigzagged = (uint64_t)(~(value << 1));
369     else
370         zigzagged = (uint64_t)(value << 1);
371     
372     return pb_encode_varint(stream, zigzagged);
373 }
374
375 bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
376 {
377     #ifdef __BIG_ENDIAN__
378     const uint8_t *bytes = value;
379     uint8_t lebytes[4];
380     lebytes[0] = bytes[3];
381     lebytes[1] = bytes[2];
382     lebytes[2] = bytes[1];
383     lebytes[3] = bytes[0];
384     return pb_write(stream, lebytes, 4);
385     #else
386     return pb_write(stream, (const uint8_t*)value, 4);
387     #endif
388 }
389
390 bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
391 {
392     #ifdef __BIG_ENDIAN__
393     const uint8_t *bytes = value;
394     uint8_t lebytes[8];
395     lebytes[0] = bytes[7];
396     lebytes[1] = bytes[6];
397     lebytes[2] = bytes[5];
398     lebytes[3] = bytes[4];
399     lebytes[4] = bytes[3];
400     lebytes[5] = bytes[2];
401     lebytes[6] = bytes[1];
402     lebytes[7] = bytes[0];
403     return pb_write(stream, lebytes, 8);
404     #else
405     return pb_write(stream, (const uint8_t*)value, 8);
406     #endif
407 }
408
409 bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
410 {
411     uint64_t tag = wiretype | (field_number << 3);
412     return pb_encode_varint(stream, tag);
413 }
414
415 bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
416 {
417     pb_wire_type_t wiretype;
418     switch (PB_LTYPE(field->type))
419     {
420         case PB_LTYPE_VARINT:
421         case PB_LTYPE_SVARINT:
422             wiretype = PB_WT_VARINT;
423             break;
424         
425         case PB_LTYPE_FIXED32:
426             wiretype = PB_WT_32BIT;
427             break;
428         
429         case PB_LTYPE_FIXED64:
430             wiretype = PB_WT_64BIT;
431             break;
432         
433         case PB_LTYPE_BYTES:
434         case PB_LTYPE_STRING:
435         case PB_LTYPE_SUBMESSAGE:
436             wiretype = PB_WT_STRING;
437             break;
438         
439         default:
440             PB_RETURN_ERROR(stream, "invalid field type");
441     }
442     
443     return pb_encode_tag(stream, wiretype, field->tag);
444 }
445
446 bool checkreturn pb_encode_string(pb_ostream_t *stream, const uint8_t *buffer, size_t size)
447 {
448     if (!pb_encode_varint(stream, (uint64_t)size))
449         return false;
450     
451     return pb_write(stream, buffer, size);
452 }
453
454 bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
455 {
456     /* First calculate the message size using a non-writing substream. */
457     pb_ostream_t substream = PB_OSTREAM_SIZING;
458     size_t size;
459     bool status;
460     
461     if (!pb_encode(&substream, fields, src_struct))
462         return false;
463     
464     size = substream.bytes_written;
465     
466     if (!pb_encode_varint(stream, (uint64_t)size))
467         return false;
468     
469     if (stream->callback == NULL)
470         return pb_write(stream, NULL, size); /* Just sizing */
471     
472     if (stream->bytes_written + size > stream->max_size)
473         PB_RETURN_ERROR(stream, "stream full");
474         
475     /* Use a substream to verify that a callback doesn't write more than
476      * what it did the first time. */
477     substream.callback = stream->callback;
478     substream.state = stream->state;
479     substream.max_size = size;
480     substream.bytes_written = 0;
481 #ifndef PB_NO_ERRMSG
482     substream.errmsg = NULL;
483 #endif
484     
485     status = pb_encode(&substream, fields, src_struct);
486     
487     stream->bytes_written += substream.bytes_written;
488     stream->state = substream.state;
489 #ifndef PB_NO_ERRMSG
490     stream->errmsg = substream.errmsg;
491 #endif
492     
493     if (substream.bytes_written != size)
494         PB_RETURN_ERROR(stream, "submsg size changed");
495     
496     return status;
497 }
498
499 /* Field encoders */
500
501 bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
502 {
503     uint64_t value = 0;
504     
505     switch (field->data_size)
506     {
507         case 1: value = *(const uint8_t*)src; break;
508         case 2: value = *(const uint16_t*)src; break;
509         case 4: value = *(const uint32_t*)src; break;
510         case 8: value = *(const uint64_t*)src; break;
511         default: PB_RETURN_ERROR(stream, "invalid data_size");
512     }
513     
514     return pb_encode_varint(stream, value);
515 }
516
517 bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
518 {
519     int64_t value = 0;
520     
521     switch (field->data_size)
522     {
523         case 4: value = *(const int32_t*)src; break;
524         case 8: value = *(const int64_t*)src; break;
525         default: PB_RETURN_ERROR(stream, "invalid data_size");
526     }
527     
528     return pb_encode_svarint(stream, value);
529 }
530
531 bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
532 {
533     UNUSED(field);
534     return pb_encode_fixed64(stream, src);
535 }
536
537 bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
538 {
539     UNUSED(field);
540     return pb_encode_fixed32(stream, src);
541 }
542
543 bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
544 {
545     const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;
546
547     if (bytes->size + offsetof(pb_bytes_array_t, bytes) > field->data_size)
548         PB_RETURN_ERROR(stream, "bytes size exceeded");
549     
550     return pb_encode_string(stream, bytes->bytes, bytes->size);
551 }
552
553 bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
554 {
555     /* strnlen() is not always available, so just use a for-loop */
556     size_t size = 0;
557     const char *p = (const char*)src;
558     while (size < field->data_size && *p != '\0')
559     {
560         size++;
561         p++;
562     }
563
564     return pb_encode_string(stream, (const uint8_t*)src, size);
565 }
566
567 bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
568 {
569     if (field->ptr == NULL)
570         PB_RETURN_ERROR(stream, "invalid field descriptor");
571     
572     return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
573 }
574