MOS Source Code
Loading...
Searching...
No Matches
pb_encode.c
Go to the documentation of this file.
1/* pb_encode.c -- encode a protobuf using minimal resources
2 *
3 * 2011 Petteri Aimonen <jpa@kapsi.fi>
4 */
5
6#include "pb.h"
7#include "pb_encode.h"
8#include "pb_common.h"
9
10/* Use the GCC warn_unused_result attribute to check that all return values
11 * are propagated correctly. On other compilers, gcc before 3.4.0 and iar
12 * before 9.40.1 just ignore the annotation.
13 */
14#if (defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))) || \
15 (defined(__IAR_SYSTEMS_ICC__) && (__VER__ >= 9040001))
16 #define checkreturn __attribute__((warn_unused_result))
17#else
18 #define checkreturn
19#endif
20
21/**************************************
22 * Declarations internal to this file *
23 **************************************/
24static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
25static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field);
26static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field);
27static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field);
28static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field);
29static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field);
30static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field);
31static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
32static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high);
33static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field);
34static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field);
35static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field);
36static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
37static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field);
38static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field);
39static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field);
40
41#ifdef PB_WITHOUT_64BIT
42#define pb_int64_t int32_t
43#define pb_uint64_t uint32_t
44#else
45#define pb_int64_t int64_t
46#define pb_uint64_t uint64_t
47#endif
48
49/*******************************
50 * pb_ostream_t implementation *
51 *******************************/
52
53static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
54{
55 pb_byte_t *dest = (pb_byte_t*)stream->state;
56 stream->state = dest + count;
57
58 memcpy(dest, buf, count * sizeof(pb_byte_t));
59
60 return true;
61}
62
63pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
64{
65 pb_ostream_t stream;
66#ifdef PB_BUFFER_ONLY
67 /* In PB_BUFFER_ONLY configuration the callback pointer is just int*.
68 * NULL pointer marks a sizing field, so put a non-NULL value to mark a buffer stream.
69 */
70 static const int marker = 0;
71 stream.callback = &marker;
72#else
73 stream.callback = &buf_write;
74#endif
75 stream.state = buf;
76 stream.max_size = bufsize;
77 stream.bytes_written = 0;
78#ifndef PB_NO_ERRMSG
79 stream.errmsg = NULL;
80#endif
81 return stream;
82}
83
84bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
85{
86 if (count > 0 && stream->callback != NULL)
87 {
88 if (stream->bytes_written + count < stream->bytes_written ||
89 stream->bytes_written + count > stream->max_size)
90 {
91 PB_RETURN_ERROR(stream, "stream full");
92 }
93
94#ifdef PB_BUFFER_ONLY
95 if (!buf_write(stream, buf, count))
96 PB_RETURN_ERROR(stream, "io error");
97#else
98 if (!stream->callback(stream, buf, count))
99 PB_RETURN_ERROR(stream, "io error");
100#endif
101 }
102
103 stream->bytes_written += count;
104 return true;
105}
106
107/*************************
108 * Encode a single field *
109 *************************/
110
111/* Read a bool value without causing undefined behavior even if the value
112 * is invalid. See issue #434 and
113 * https://stackoverflow.com/questions/27661768/weird-results-for-conditional
114 */
115static bool safe_read_bool(const void *pSize)
116{
117 const char *p = (const char *)pSize;
118 size_t i;
119 for (i = 0; i < sizeof(bool); i++)
120 {
121 if (p[i] != 0)
122 return true;
123 }
124 return false;
125}
126
127/* Encode a static array. Handles the size calculations and possible packing. */
128static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field)
129{
130 pb_size_t i;
131 pb_size_t count;
132#ifndef PB_ENCODE_ARRAYS_UNPACKED
133 size_t size;
134#endif
135
136 count = *(pb_size_t*)field->pSize;
137
138 if (count == 0)
139 return true;
140
141 if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
142 PB_RETURN_ERROR(stream, "array max size exceeded");
143
144#ifndef PB_ENCODE_ARRAYS_UNPACKED
145 /* We always pack arrays if the datatype allows it. */
146 if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
147 {
148 if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
149 return false;
150
151 /* Determine the total size of packed array. */
152 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
153 {
154 size = 4 * (size_t)count;
155 }
156 else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
157 {
158 size = 8 * (size_t)count;
159 }
160 else
161 {
162 pb_ostream_t sizestream = PB_OSTREAM_SIZING;
163 void *pData_orig = field->pData;
164 for (i = 0; i < count; i++)
165 {
166 if (!pb_enc_varint(&sizestream, field))
167 PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream));
168 field->pData = (char*)field->pData + field->data_size;
169 }
170 field->pData = pData_orig;
171 size = sizestream.bytes_written;
172 }
173
174 if (!pb_encode_varint(stream, (pb_uint64_t)size))
175 return false;
176
177 if (stream->callback == NULL)
178 return pb_write(stream, NULL, size); /* Just sizing.. */
179
180 /* Write the data */
181 for (i = 0; i < count; i++)
182 {
183 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
184 {
185 if (!pb_enc_fixed(stream, field))
186 return false;
187 }
188 else
189 {
190 if (!pb_enc_varint(stream, field))
191 return false;
192 }
193
194 field->pData = (char*)field->pData + field->data_size;
195 }
196 }
197 else /* Unpacked fields */
198#endif
199 {
200 for (i = 0; i < count; i++)
201 {
202 /* Normally the data is stored directly in the array entries, but
203 * for pointer-type string and bytes fields, the array entries are
204 * actually pointers themselves also. So we have to dereference once
205 * more to get to the actual data. */
206 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
207 (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
208 PB_LTYPE(field->type) == PB_LTYPE_BYTES))
209 {
210 bool status;
211 void *pData_orig = field->pData;
212 field->pData = *(void* const*)field->pData;
213
214 if (!field->pData)
215 {
216 /* Null pointer in array is treated as empty string / bytes */
217 status = pb_encode_tag_for_field(stream, field) &&
218 pb_encode_varint(stream, 0);
219 }
220 else
221 {
222 status = encode_basic_field(stream, field);
223 }
224
225 field->pData = pData_orig;
226
227 if (!status)
228 return false;
229 }
230 else
231 {
232 if (!encode_basic_field(stream, field))
233 return false;
234 }
235 field->pData = (char*)field->pData + field->data_size;
236 }
237 }
238
239 return true;
240}
241
242/* In proto3, all fields are optional and are only encoded if their value is "non-zero".
243 * This function implements the check for the zero value. */
244static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field)
245{
246 pb_type_t type = field->type;
247
248 if (PB_ATYPE(type) == PB_ATYPE_STATIC)
249 {
250 if (PB_HTYPE(type) == PB_HTYPE_REQUIRED)
251 {
252 /* Required proto2 fields inside proto3 submessage, pretty rare case */
253 return false;
254 }
255 else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
256 {
257 /* Repeated fields inside proto3 submessage: present if count != 0 */
258 return *(const pb_size_t*)field->pSize == 0;
259 }
260 else if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
261 {
262 /* Oneof fields */
263 return *(const pb_size_t*)field->pSize == 0;
264 }
265 else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL)
266 {
267 /* Proto2 optional fields inside proto3 message, or proto3
268 * submessage fields. */
269 return safe_read_bool(field->pSize) == false;
270 }
271 else if (field->descriptor->default_value)
272 {
273 /* Proto3 messages do not have default values, but proto2 messages
274 * can contain optional fields without has_fields (generator option 'proto3').
275 * In this case they must always be encoded, to make sure that the
276 * non-zero default value is overwritten.
277 */
278 return false;
279 }
280
281 /* Rest is proto3 singular fields */
282 if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
283 {
284 /* Simple integer / float fields */
285 pb_size_t i;
286 const char *p = (const char*)field->pData;
287 for (i = 0; i < field->data_size; i++)
288 {
289 if (p[i] != 0)
290 {
291 return false;
292 }
293 }
294
295 return true;
296 }
297 else if (PB_LTYPE(type) == PB_LTYPE_BYTES)
298 {
299 const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData;
300 return bytes->size == 0;
301 }
302 else if (PB_LTYPE(type) == PB_LTYPE_STRING)
303 {
304 return *(const char*)field->pData == '\0';
305 }
306 else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES)
307 {
308 /* Fixed length bytes is only empty if its length is fixed
309 * as 0. Which would be pretty strange, but we can check
310 * it anyway. */
311 return field->data_size == 0;
312 }
313 else if (PB_LTYPE_IS_SUBMSG(type))
314 {
315 /* Check all fields in the submessage to find if any of them
316 * are non-zero. The comparison cannot be done byte-per-byte
317 * because the C struct may contain padding bytes that must
318 * be skipped. Note that usually proto3 submessages have
319 * a separate has_field that is checked earlier in this if.
320 */
321 pb_field_iter_t iter;
322 if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData))
323 {
324 do
325 {
327 {
328 return false;
329 }
330 } while (pb_field_iter_next(&iter));
331 }
332 return true;
333 }
334 }
335 else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
336 {
337 return field->pData == NULL;
338 }
339 else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
340 {
341 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
342 {
343 const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
344 return extension == NULL;
345 }
346 else if (field->descriptor->field_callback == pb_default_field_callback)
347 {
348 pb_callback_t *pCallback = (pb_callback_t*)field->pData;
349 return pCallback->funcs.encode == NULL;
350 }
351 else
352 {
353 return field->descriptor->field_callback == NULL;
354 }
355 }
356
357 return false; /* Not typically reached, safe default for weird special cases. */
358}
359
360/* Encode a field with static or pointer allocation, i.e. one whose data
361 * is available to the encoder directly. */
362static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field)
363{
364 if (!field->pData)
365 {
366 /* Missing pointer field */
367 return true;
368 }
369
370 if (!pb_encode_tag_for_field(stream, field))
371 return false;
372
373 switch (PB_LTYPE(field->type))
374 {
375 case PB_LTYPE_BOOL:
376 return pb_enc_bool(stream, field);
377
378 case PB_LTYPE_VARINT:
379 case PB_LTYPE_UVARINT:
380 case PB_LTYPE_SVARINT:
381 return pb_enc_varint(stream, field);
382
383 case PB_LTYPE_FIXED32:
384 case PB_LTYPE_FIXED64:
385 return pb_enc_fixed(stream, field);
386
387 case PB_LTYPE_BYTES:
388 return pb_enc_bytes(stream, field);
389
390 case PB_LTYPE_STRING:
391 return pb_enc_string(stream, field);
392
395 return pb_enc_submessage(stream, field);
396
398 return pb_enc_fixed_length_bytes(stream, field);
399
400 default:
401 PB_RETURN_ERROR(stream, "invalid field type");
402 }
403}
404
405/* Encode a field with callback semantics. This means that a user function is
406 * called to provide and encode the actual data. */
407static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field)
408{
409 if (field->descriptor->field_callback != NULL)
410 {
411 if (!field->descriptor->field_callback(NULL, stream, field))
412 PB_RETURN_ERROR(stream, "callback error");
413 }
414 return true;
415}
416
417/* Encode a single field of any callback, pointer or static type. */
418static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field)
419{
420 /* Check field presence */
421 if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
422 {
423 if (*(const pb_size_t*)field->pSize != field->tag)
424 {
425 /* Different type oneof field */
426 return true;
427 }
428 }
429 else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
430 {
431 if (field->pSize)
432 {
433 if (safe_read_bool(field->pSize) == false)
434 {
435 /* Missing optional field */
436 return true;
437 }
438 }
439 else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC)
440 {
441 /* Proto3 singular field */
443 return true;
444 }
445 }
446
447 if (!field->pData)
448 {
449 if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED)
450 PB_RETURN_ERROR(stream, "missing required field");
451
452 /* Pointer field set to NULL */
453 return true;
454 }
455
456 /* Then encode field contents */
457 if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK)
458 {
459 return encode_callback_field(stream, field);
460 }
461 else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED)
462 {
463 return encode_array(stream, field);
464 }
465 else
466 {
467 return encode_basic_field(stream, field);
468 }
469}
470
471/* Default handler for extension fields. Expects to have a pb_msgdesc_t
472 * pointer in the extension->type->arg field, pointing to a message with
473 * only one field in it. */
474static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension)
475{
476 pb_field_iter_t iter;
477
478 if (!pb_field_iter_begin_extension_const(&iter, extension))
479 PB_RETURN_ERROR(stream, "invalid extension");
480
481 return encode_field(stream, &iter);
482}
483
484
485/* Walk through all the registered extensions and give them a chance
486 * to encode themselves. */
487static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field)
488{
489 const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
490
491 while (extension)
492 {
493 bool status;
494 if (extension->type->encode)
495 status = extension->type->encode(stream, extension);
496 else
497 status = default_extension_encoder(stream, extension);
498
499 if (!status)
500 return false;
501
502 extension = extension->next;
503 }
504
505 return true;
506}
507
508/*********************
509 * Encode all fields *
510 *********************/
511
512bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
513{
514 pb_field_iter_t iter;
515 if (!pb_field_iter_begin_const(&iter, fields, src_struct))
516 return true; /* Empty message type */
517
518 do {
519 if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
520 {
521 /* Special case for the extension field placeholder */
522 if (!encode_extension_field(stream, &iter))
523 return false;
524 }
525 else
526 {
527 /* Regular field */
528 if (!encode_field(stream, &iter))
529 return false;
530 }
531 } while (pb_field_iter_next(&iter));
532
533 return true;
534}
535
536bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags)
537{
538 if ((flags & PB_ENCODE_DELIMITED) != 0)
539 {
540 return pb_encode_submessage(stream, fields, src_struct);
541 }
542 else if ((flags & PB_ENCODE_NULLTERMINATED) != 0)
543 {
544 const pb_byte_t zero = 0;
545
546 if (!pb_encode(stream, fields, src_struct))
547 return false;
548
549 return pb_write(stream, &zero, 1);
550 }
551 else
552 {
553 return pb_encode(stream, fields, src_struct);
554 }
555}
556
557bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct)
558{
559 pb_ostream_t stream = PB_OSTREAM_SIZING;
560
561 if (!pb_encode(&stream, fields, src_struct))
562 return false;
563
564 *size = stream.bytes_written;
565 return true;
566}
567
568/********************
569 * Helper functions *
570 ********************/
571
572/* This function avoids 64-bit shifts as they are quite slow on many platforms. */
573static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high)
574{
575 size_t i = 0;
576 pb_byte_t buffer[10];
577 pb_byte_t byte = (pb_byte_t)(low & 0x7F);
578 low >>= 7;
579
580 while (i < 4 && (low != 0 || high != 0))
581 {
582 byte |= 0x80;
583 buffer[i++] = byte;
584 byte = (pb_byte_t)(low & 0x7F);
585 low >>= 7;
586 }
587
588 if (high)
589 {
590 byte = (pb_byte_t)(byte | ((high & 0x07) << 4));
591 high >>= 3;
592
593 while (high)
594 {
595 byte |= 0x80;
596 buffer[i++] = byte;
597 byte = (pb_byte_t)(high & 0x7F);
598 high >>= 7;
599 }
600 }
601
602 buffer[i++] = byte;
603
604 return pb_write(stream, buffer, i);
605}
606
607bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value)
608{
609 if (value <= 0x7F)
610 {
611 /* Fast path: single byte */
612 pb_byte_t byte = (pb_byte_t)value;
613 return pb_write(stream, &byte, 1);
614 }
615 else
616 {
617#ifdef PB_WITHOUT_64BIT
618 return pb_encode_varint_32(stream, value, 0);
619#else
620 return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32));
621#endif
622 }
623}
624
625bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value)
626{
627 pb_uint64_t zigzagged;
628 pb_uint64_t mask = ((pb_uint64_t)-1) >> 1; /* Satisfy clang -fsanitize=integer */
629 if (value < 0)
630 zigzagged = ~(((pb_uint64_t)value & mask) << 1);
631 else
632 zigzagged = (pb_uint64_t)value << 1;
633
634 return pb_encode_varint(stream, zigzagged);
635}
636
637bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
638{
639#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
640 /* Fast path if we know that we're on little endian */
641 return pb_write(stream, (const pb_byte_t*)value, 4);
642#else
643 uint32_t val = *(const uint32_t*)value;
644 pb_byte_t bytes[4];
645 bytes[0] = (pb_byte_t)(val & 0xFF);
646 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
647 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
648 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
649 return pb_write(stream, bytes, 4);
650#endif
651}
652
653#ifndef PB_WITHOUT_64BIT
654bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
655{
656#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
657 /* Fast path if we know that we're on little endian */
658 return pb_write(stream, (const pb_byte_t*)value, 8);
659#else
660 uint64_t val = *(const uint64_t*)value;
661 pb_byte_t bytes[8];
662 bytes[0] = (pb_byte_t)(val & 0xFF);
663 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
664 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
665 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
666 bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
667 bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
668 bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
669 bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
670 return pb_write(stream, bytes, 8);
671#endif
672}
673#endif
674
675bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
676{
677 pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype;
678 return pb_encode_varint(stream, tag);
679}
680
681bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field )
682{
683 pb_wire_type_t wiretype;
684 switch (PB_LTYPE(field->type))
685 {
686 case PB_LTYPE_BOOL:
687 case PB_LTYPE_VARINT:
688 case PB_LTYPE_UVARINT:
689 case PB_LTYPE_SVARINT:
690 wiretype = PB_WT_VARINT;
691 break;
692
693 case PB_LTYPE_FIXED32:
694 wiretype = PB_WT_32BIT;
695 break;
696
697 case PB_LTYPE_FIXED64:
698 wiretype = PB_WT_64BIT;
699 break;
700
701 case PB_LTYPE_BYTES:
702 case PB_LTYPE_STRING:
706 wiretype = PB_WT_STRING;
707 break;
708
709 default:
710 PB_RETURN_ERROR(stream, "invalid field type");
711 }
712
713 return pb_encode_tag(stream, wiretype, field->tag);
714}
715
716bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
717{
718 if (!pb_encode_varint(stream, (pb_uint64_t)size))
719 return false;
720
721 return pb_write(stream, buffer, size);
722}
723
724bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
725{
726 /* First calculate the message size using a non-writing substream. */
727 pb_ostream_t substream = PB_OSTREAM_SIZING;
728 size_t size;
729 bool status;
730
731 if (!pb_encode(&substream, fields, src_struct))
732 {
733#ifndef PB_NO_ERRMSG
734 stream->errmsg = substream.errmsg;
735#endif
736 return false;
737 }
738
739 size = substream.bytes_written;
740
741 if (!pb_encode_varint(stream, (pb_uint64_t)size))
742 return false;
743
744 if (stream->callback == NULL)
745 return pb_write(stream, NULL, size); /* Just sizing */
746
747 if (stream->bytes_written + size > stream->max_size)
748 PB_RETURN_ERROR(stream, "stream full");
749
750 /* Use a substream to verify that a callback doesn't write more than
751 * what it did the first time. */
752 substream.callback = stream->callback;
753 substream.state = stream->state;
754 substream.max_size = size;
755 substream.bytes_written = 0;
756#ifndef PB_NO_ERRMSG
757 substream.errmsg = NULL;
758#endif
759
760 status = pb_encode(&substream, fields, src_struct);
761
762 stream->bytes_written += substream.bytes_written;
763 stream->state = substream.state;
764#ifndef PB_NO_ERRMSG
765 stream->errmsg = substream.errmsg;
766#endif
767
768 if (substream.bytes_written != size)
769 PB_RETURN_ERROR(stream, "submsg size changed");
770
771 return status;
772}
773
774/* Field encoders */
775
776static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field)
777{
778 uint32_t value = safe_read_bool(field->pData) ? 1 : 0;
779 PB_UNUSED(field);
780 return pb_encode_varint(stream, value);
781}
782
783static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field)
784{
785 if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT)
786 {
787 /* Perform unsigned integer extension */
788 pb_uint64_t value = 0;
789
790 if (field->data_size == sizeof(uint_least8_t))
791 value = *(const uint_least8_t*)field->pData;
792 else if (field->data_size == sizeof(uint_least16_t))
793 value = *(const uint_least16_t*)field->pData;
794 else if (field->data_size == sizeof(uint32_t))
795 value = *(const uint32_t*)field->pData;
796 else if (field->data_size == sizeof(pb_uint64_t))
797 value = *(const pb_uint64_t*)field->pData;
798 else
799 PB_RETURN_ERROR(stream, "invalid data_size");
800
801 return pb_encode_varint(stream, value);
802 }
803 else
804 {
805 /* Perform signed integer extension */
806 pb_int64_t value = 0;
807
808 if (field->data_size == sizeof(int_least8_t))
809 value = *(const int_least8_t*)field->pData;
810 else if (field->data_size == sizeof(int_least16_t))
811 value = *(const int_least16_t*)field->pData;
812 else if (field->data_size == sizeof(int32_t))
813 value = *(const int32_t*)field->pData;
814 else if (field->data_size == sizeof(pb_int64_t))
815 value = *(const pb_int64_t*)field->pData;
816 else
817 PB_RETURN_ERROR(stream, "invalid data_size");
818
819 if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT)
820 return pb_encode_svarint(stream, value);
821#ifdef PB_WITHOUT_64BIT
822 else if (value < 0)
823 return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1);
824#endif
825 else
826 return pb_encode_varint(stream, (pb_uint64_t)value);
827
828 }
829}
830
831static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field)
832{
833#ifdef PB_CONVERT_DOUBLE_FLOAT
834 if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
835 {
836 return pb_encode_float_as_double(stream, *(float*)field->pData);
837 }
838#endif
839
840 if (field->data_size == sizeof(uint32_t))
841 {
842 return pb_encode_fixed32(stream, field->pData);
843 }
844#ifndef PB_WITHOUT_64BIT
845 else if (field->data_size == sizeof(uint64_t))
846 {
847 return pb_encode_fixed64(stream, field->pData);
848 }
849#endif
850 else
851 {
852 PB_RETURN_ERROR(stream, "invalid data_size");
853 }
854}
855
856static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
857{
858 const pb_bytes_array_t *bytes = NULL;
859
860 bytes = (const pb_bytes_array_t*)field->pData;
861
862 if (bytes == NULL)
863 {
864 /* Treat null pointer as an empty bytes field */
865 return pb_encode_string(stream, NULL, 0);
866 }
867
868 if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
869 bytes->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
870 {
871 PB_RETURN_ERROR(stream, "bytes size exceeded");
872 }
873
874 return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size);
875}
876
877static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field)
878{
879 size_t size = 0;
880 size_t max_size = (size_t)field->data_size;
881 const char *str = (const char*)field->pData;
882
883 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
884 {
885 max_size = (size_t)-1;
886 }
887 else
888 {
889 /* pb_dec_string() assumes string fields end with a null
890 * terminator when the type isn't PB_ATYPE_POINTER, so we
891 * shouldn't allow more than max-1 bytes to be written to
892 * allow space for the null terminator.
893 */
894 if (max_size == 0)
895 PB_RETURN_ERROR(stream, "zero-length string");
896
897 max_size -= 1;
898 }
899
900
901 if (str == NULL)
902 {
903 size = 0; /* Treat null pointer as an empty string */
904 }
905 else
906 {
907 const char *p = str;
908
909 /* strnlen() is not always available, so just use a loop */
910 while (size < max_size && *p != '\0')
911 {
912 size++;
913 p++;
914 }
915
916 if (*p != '\0')
917 {
918 PB_RETURN_ERROR(stream, "unterminated string");
919 }
920 }
921
922#ifdef PB_VALIDATE_UTF8
923 if (!pb_validate_utf8(str))
924 PB_RETURN_ERROR(stream, "invalid utf8");
925#endif
926
927 return pb_encode_string(stream, (const pb_byte_t*)str, size);
928}
929
930static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field)
931{
932 if (field->submsg_desc == NULL)
933 PB_RETURN_ERROR(stream, "invalid field descriptor");
934
935 if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL)
936 {
937 /* Message callback is stored right before pSize. */
938 pb_callback_t *callback = (pb_callback_t*)field->pSize - 1;
939 if (callback->funcs.encode)
940 {
941 if (!callback->funcs.encode(stream, field, &callback->arg))
942 return false;
943 }
944 }
945
946 return pb_encode_submessage(stream, field->submsg_desc, field->pData);
947}
948
949static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
950{
951 return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size);
952}
953
954#ifdef PB_CONVERT_DOUBLE_FLOAT
955bool pb_encode_float_as_double(pb_ostream_t *stream, float value)
956{
957 union { float f; uint32_t i; } in;
958 uint_least8_t sign;
959 int exponent;
960 uint64_t mantissa;
961
962 in.f = value;
963
964 /* Decompose input value */
965 sign = (uint_least8_t)((in.i >> 31) & 1);
966 exponent = (int)((in.i >> 23) & 0xFF) - 127;
967 mantissa = in.i & 0x7FFFFF;
968
969 if (exponent == 128)
970 {
971 /* Special value (NaN etc.) */
972 exponent = 1024;
973 }
974 else if (exponent == -127)
975 {
976 if (!mantissa)
977 {
978 /* Zero */
979 exponent = -1023;
980 }
981 else
982 {
983 /* Denormalized */
984 mantissa <<= 1;
985 while (!(mantissa & 0x800000))
986 {
987 mantissa <<= 1;
988 exponent--;
989 }
990 mantissa &= 0x7FFFFF;
991 }
992 }
993
994 /* Combine fields */
995 mantissa <<= 29;
996 mantissa |= (uint64_t)(exponent + 1023) << 52;
997 mantissa |= (uint64_t)sign << 63;
998
999 return pb_encode_fixed64(stream, &mantissa);
1000}
1001#endif
bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
const reg32_t low
Definition fpu_context.c:23
const reg32_t high
Definition fpu_context.c:24
MOSAPI int(2, 3) sprintf(char *__restrict str
#define uint64_t
#define PB_HTYPE(x)
Definition pb.h:298
#define PB_LTYPE_SUBMSG_W_CB
Definition pb.h:264
uint_least8_t pb_byte_t
Definition pb.h:227
#define PB_GET_ERROR(stream)
Definition pb.h:891
#define PB_LTYPE_EXTENSION
Definition pb.h:268
#define PB_UNUSED(x)
Definition pb.h:143
#define PB_ATYPE_CALLBACK
Definition pb.h:294
#define PB_ATYPE_STATIC
Definition pb.h:292
uint_least16_t pb_size_t
Definition pb.h:310
#define PB_LTYPE_STRING
Definition pb.h:255
#define PB_ATYPE_POINTER
Definition pb.h:293
#define PB_LTYPE_BOOL
Definition pb.h:239
bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
Definition pb_common.c:300
#define PB_LTYPE_FIXED64
Definition pb.h:244
#define PB_HTYPE_REQUIRED
Definition pb.h:282
#define PB_LTYPE_LAST_PACKABLE
Definition pb.h:247
#define PB_LTYPE_SVARINT
Definition pb.h:242
#define PB_HTYPE_ONEOF
Definition pb.h:287
#define PB_ATYPE(x)
Definition pb.h:297
#define PB_HTYPE_OPTIONAL
Definition pb.h:283
#define PB_LTYPE_UVARINT
Definition pb.h:241
#define PB_LTYPE(x)
Definition pb.h:299
#define PB_HTYPE_REPEATED
Definition pb.h:285
#define PB_LTYPE_FIXED_LENGTH_BYTES
Definition pb.h:274
#define PB_LTYPE_VARINT
Definition pb.h:240
#define PB_LTYPE_BYTES
Definition pb.h:251
pb_wire_type_t
Definition pb.h:420
@ PB_WT_VARINT
Definition pb.h:421
@ PB_WT_32BIT
Definition pb.h:424
@ PB_WT_STRING
Definition pb.h:423
@ PB_WT_64BIT
Definition pb.h:422
#define PB_RETURN_ERROR(stream, msg)
Definition pb.h:894
#define PB_LTYPE_IS_SUBMSG(x)
Definition pb.h:300
#define PB_LTYPE_FIXED32
Definition pb.h:243
#define PB_LTYPE_SUBMESSAGE
Definition pb.h:259
pb_byte_t pb_type_t
Definition pb.h:234
bool pb_field_iter_next(pb_field_iter_t *iter)
Definition pb_common.c:188
bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension)
Definition pb_common.c:295
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message)
Definition pb_common.c:156
bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message)
Definition pb_common.c:290
static bool buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
Definition pb_encode.c:53
static bool encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:487
bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags)
Definition pb_encode.c:536
static bool pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high)
Definition pb_encode.c:573
#define pb_uint64_t
Definition pb_encode.c:46
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:681
static bool encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:407
static bool pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:877
static bool pb_check_proto3_default_value(const pb_field_iter_t *field)
Definition pb_encode.c:244
bool pb_encode_varint(pb_ostream_t *stream, uint64_t value)
Definition pb_encode.c:607
static bool encode_field(pb_ostream_t *stream, pb_field_iter_t *field)
Definition pb_encode.c:418
#define pb_int64_t
Definition pb_encode.c:45
bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
Definition pb_encode.c:724
static bool encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:362
bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
Definition pb_encode.c:84
bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct)
Definition pb_encode.c:557
static bool pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:831
static bool pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:949
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
Definition pb_encode.c:63
static bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:930
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value)
Definition pb_encode.c:654
#define checkreturn
Definition pb_encode.c:18
static bool default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension)
Definition pb_encode.c:474
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
Definition pb_encode.c:675
static bool pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:856
bool pb_encode_fixed32(pb_ostream_t *stream, const void *value)
Definition pb_encode.c:637
static bool safe_read_bool(const void *pSize)
Definition pb_encode.c:115
bool pb_encode_svarint(pb_ostream_t *stream, int64_t value)
Definition pb_encode.c:625
bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct)
Definition pb_encode.c:512
static bool pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:776
bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
Definition pb_encode.c:716
static bool encode_array(pb_ostream_t *stream, pb_field_iter_t *field)
Definition pb_encode.c:128
static bool pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field)
Definition pb_encode.c:783
#define PB_OSTREAM_SIZING
Definition pb_encode.h:116
#define PB_ENCODE_NULLTERMINATED
Definition pb_encode.h:82
#define PB_ENCODE_DELIMITED
Definition pb_encode.h:81
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
int bool
Definition pb_syshdr.h:57
int16_t int_least16_t
Definition pb_syshdr.h:33
#define offsetof(st, m)
Definition pb_syshdr.h:43
uint32_t size_t
Definition pb_syshdr.h:42
unsigned int uint32_t
Definition pb_syshdr.h:24
uint16_t uint_least16_t
Definition pb_syshdr.h:34
unsigned long long uint64_t
Definition pb_syshdr.h:26
int8_t int_least8_t
Definition pb_syshdr.h:30
signed int int32_t
Definition pb_syshdr.h:23
uint8_t uint_least8_t
Definition pb_syshdr.h:31
size_t size
Definition slab.c:30
static char buffer[2048]
Definition test_printf.c:7