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