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