14#if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
17#define checkreturn __attribute__((warn_unused_result))
23static bool checkreturn buf_write(
pb_ostream_t *
stream,
const pb_byte_t *buf,
size_t count);
25static bool checkreturn pb_check_proto3_default_value(
const pb_field_iter_t *field);
31static bool checkreturn pb_encode_varint_32(
pb_ostream_t *
stream, uint32_t low, uint32_t high);
40#ifdef PB_WITHOUT_64BIT
41#define pb_int64_t int32_t
42#define pb_uint64_t uint32_t
44#define pb_int64_t int64_t
45#define pb_uint64_t uint64_t
51static bool checkreturn buf_write(
pb_ostream_t *
stream,
const pb_byte_t *buf,
size_t count) {
52 pb_byte_t *dest = (pb_byte_t *)
stream->state;
54 stream->state = dest + count;
56 memcpy(dest, buf, count *
sizeof(pb_byte_t));
61pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf,
size_t bufsize) {
68 static const int marker = 0;
71 stream.callback = &buf_write;
83 if (count > 0 &&
stream->callback != NULL) {
84 if (
stream->bytes_written + count < stream->bytes_written ||
86 PB_RETURN_ERROR(
stream,
"stream full");
90 if (!buf_write(
stream, buf, count)) {
91 PB_RETURN_ERROR(
stream,
"io error");
95 PB_RETURN_ERROR(
stream,
"io error");
100 stream->bytes_written += count;
112static bool safe_read_bool(
const void *pSize) {
113 const char *p = (
const char *)pSize;
116 for (i = 0; i <
sizeof(bool); i++) {
129#ifndef PB_ENCODE_ARRAYS_UNPACKED
133 count = *(pb_size_t *)field->pSize;
139 if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) {
140 PB_RETURN_ERROR(
stream,
"array max size exceeded");
143#ifndef PB_ENCODE_ARRAYS_UNPACKED
145 if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) {
146 if (!pb_encode_tag(
stream, PB_WT_STRING, field->tag)) {
151 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) {
152 size = 4 * (size_t)count;
153 }
else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) {
154 size = 8 * (size_t)count;
157 void *pData_orig = field->pData;
158 for (i = 0; i < count; i++) {
159 if (!pb_enc_varint(&sizestream, field)) {
160 PB_RETURN_ERROR(
stream, PB_GET_ERROR(&sizestream));
162 field->pData = (
char *)field->pData + field->data_size;
164 field->pData = pData_orig;
165 size = sizestream.bytes_written;
168 if (!pb_encode_varint(
stream, (pb_uint64_t)size)) {
172 if (
stream->callback == NULL) {
173 return pb_write(
stream, NULL, size);
176 for (i = 0; i < count; i++) {
177 if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64) {
178 if (!pb_enc_fixed(
stream, field)) {
182 if (!pb_enc_varint(
stream, field)) {
187 field->pData = (
char *)field->pData + field->data_size;
192 for (i = 0; i < count; i++) {
197 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
198 (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
199 PB_LTYPE(field->type) == PB_LTYPE_BYTES)) {
201 void *pData_orig = field->pData;
202 field->pData = *(
void *
const *)field->pData;
206 status = pb_encode_tag_for_field(
stream, field) &&
207 pb_encode_varint(
stream, 0);
209 status = encode_basic_field(
stream, field);
212 field->pData = pData_orig;
218 if (!encode_basic_field(
stream, field)) {
222 field->pData = (
char *)field->pData + field->data_size;
231static bool checkreturn pb_check_proto3_default_value(
const pb_field_iter_t *field) {
232 pb_type_t type = field->type;
234 if (PB_ATYPE(type) == PB_ATYPE_STATIC) {
235 if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) {
238 }
else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) {
240 return *(
const pb_size_t *)field->pSize == 0;
241 }
else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) {
243 return *(
const pb_size_t *)field->pSize == 0;
244 }
else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) {
247 return safe_read_bool(field->pSize) ==
false;
248 }
else if (field->descriptor->default_value) {
258 if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) {
261 const char *p = (
const char *)field->pData;
262 for (i = 0; i < field->data_size; i++) {
269 }
else if (PB_LTYPE(type) == PB_LTYPE_BYTES) {
271 return bytes->size == 0;
272 }
else if (PB_LTYPE(type) == PB_LTYPE_STRING) {
273 return *(
const char *)field->pData ==
'\0';
274 }
else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) {
278 return field->data_size == 0;
279 }
else if (PB_LTYPE_IS_SUBMSG(type)) {
287 if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData)) {
289 if (!pb_check_proto3_default_value(&iter)) {
292 }
while (pb_field_iter_next(&iter));
296 }
else if (PB_ATYPE(type) == PB_ATYPE_POINTER) {
297 return field->pData == NULL;
298 }
else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) {
299 if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) {
301 return extension == NULL;
302 }
else if (field->descriptor->field_callback == pb_default_field_callback) {
304 return pCallback->funcs.encode == NULL;
306 return field->descriptor->field_callback == NULL;
321 if (!pb_encode_tag_for_field(
stream, field)) {
325 switch (PB_LTYPE(field->type)) {
327 return pb_enc_bool(
stream, field);
329 case PB_LTYPE_VARINT:
330 case PB_LTYPE_UVARINT:
331 case PB_LTYPE_SVARINT:
332 return pb_enc_varint(
stream, field);
334 case PB_LTYPE_FIXED32:
335 case PB_LTYPE_FIXED64:
336 return pb_enc_fixed(
stream, field);
339 return pb_enc_bytes(
stream, field);
341 case PB_LTYPE_STRING:
342 return pb_enc_string(
stream, field);
344 case PB_LTYPE_SUBMESSAGE:
345 case PB_LTYPE_SUBMSG_W_CB:
346 return pb_enc_submessage(
stream, field);
348 case PB_LTYPE_FIXED_LENGTH_BYTES:
349 return pb_enc_fixed_length_bytes(
stream, field);
352 PB_RETURN_ERROR(
stream,
"invalid field type");
359 if (field->descriptor->field_callback != NULL) {
360 if (!field->descriptor->field_callback(NULL,
stream, field)) {
361 PB_RETURN_ERROR(
stream,
"callback error");
370 if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) {
371 if (*(
const pb_size_t *)field->pSize != field->tag) {
375 }
else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) {
377 if (safe_read_bool(field->pSize) ==
false) {
381 }
else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) {
383 if (pb_check_proto3_default_value(field)) {
390 if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED) {
391 PB_RETURN_ERROR(
stream,
"missing required field");
399 if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK) {
400 return encode_callback_field(
stream, field);
401 }
else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) {
402 return encode_array(
stream, field);
404 return encode_basic_field(
stream, field);
414 if (!pb_field_iter_begin_extension_const(&iter, extension)) {
415 PB_RETURN_ERROR(
stream,
"invalid extension");
418 return encode_field(
stream, &iter);
429 if (extension->type->encode) {
430 status = extension->type->encode(
stream, extension);
432 status = default_extension_encoder(
stream, extension);
439 extension = extension->next;
451 if (!pb_field_iter_begin_const(&iter, fields, src_struct)) {
455 if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) {
457 if (!encode_extension_field(
stream, &iter)) {
462 if (!encode_field(
stream, &iter)) {
466 }
while (pb_field_iter_next(&iter));
472 if ((flags & PB_ENCODE_DELIMITED) != 0) {
473 return pb_encode_submessage(
stream, fields, src_struct);
474 }
else if ((flags & PB_ENCODE_NULLTERMINATED) != 0) {
475 const pb_byte_t zero = 0;
477 if (!pb_encode(
stream, fields, src_struct)) {
481 return pb_write(
stream, &zero, 1);
483 return pb_encode(
stream, fields, src_struct);
487bool pb_get_encoded_size(
size_t *size,
const pb_msgdesc_t *fields,
const void *src_struct) {
490 if (!pb_encode(&
stream, fields, src_struct)) {
494 *size =
stream.bytes_written;
503static bool checkreturn pb_encode_varint_32(
pb_ostream_t *
stream, uint32_t low, uint32_t high) {
505 pb_byte_t buffer[10];
506 pb_byte_t
byte = (pb_byte_t)(low & 0x7F);
510 while (i < 4 && (low != 0 || high != 0)) {
513 byte = (pb_byte_t)(low & 0x7F);
518 byte = (pb_byte_t)(
byte | ((high & 0x07) << 4));
524 byte = (pb_byte_t)(high & 0x7F);
531 return pb_write(
stream, buffer, i);
537 pb_byte_t
byte = (pb_byte_t)value;
538 return pb_write(
stream, &
byte, 1);
540#ifdef PB_WITHOUT_64BIT
541 return pb_encode_varint_32(
stream, value, 0);
543 return pb_encode_varint_32(
stream, (uint32_t)value, (uint32_t)(value >> 32));
549 pb_uint64_t zigzagged;
550 pb_uint64_t mask = ((pb_uint64_t)-1) >> 1;
553 zigzagged = ~(((pb_uint64_t)value & mask) << 1);
555 zigzagged = (pb_uint64_t)value << 1;
558 return pb_encode_varint(
stream, zigzagged);
562#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
564 return pb_write(
stream, (
const pb_byte_t *)value, 4);
566 uint32_t val = *(
const uint32_t *)value;
568 bytes[0] = (pb_byte_t)(val & 0xFF);
569 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
570 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
571 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
572 return pb_write(
stream, bytes, 4);
576#ifndef PB_WITHOUT_64BIT
578#if defined(PB_LITTLE_ENDIAN_8BIT) && PB_LITTLE_ENDIAN_8BIT == 1
580 return pb_write(
stream, (
const pb_byte_t *)value, 8);
582 uint64_t val = *(
const uint64_t *)value;
584 bytes[0] = (pb_byte_t)(val & 0xFF);
585 bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
586 bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
587 bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
588 bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
589 bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
590 bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
591 bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
592 return pb_write(
stream, bytes, 8);
597bool checkreturn pb_encode_tag(
pb_ostream_t *
stream, pb_wire_type_t wiretype, uint32_t field_number) {
598 pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype;
600 return pb_encode_varint(
stream, tag);
604 pb_wire_type_t wiretype;
606 switch (PB_LTYPE(field->type)) {
608 case PB_LTYPE_VARINT:
609 case PB_LTYPE_UVARINT:
610 case PB_LTYPE_SVARINT:
611 wiretype = PB_WT_VARINT;
614 case PB_LTYPE_FIXED32:
615 wiretype = PB_WT_32BIT;
618 case PB_LTYPE_FIXED64:
619 wiretype = PB_WT_64BIT;
623 case PB_LTYPE_STRING:
624 case PB_LTYPE_SUBMESSAGE:
625 case PB_LTYPE_SUBMSG_W_CB:
626 case PB_LTYPE_FIXED_LENGTH_BYTES:
627 wiretype = PB_WT_STRING;
631 PB_RETURN_ERROR(
stream,
"invalid field type");
634 return pb_encode_tag(
stream, wiretype, field->tag);
637bool checkreturn pb_encode_string(
pb_ostream_t *
stream,
const pb_byte_t *buffer,
size_t size) {
638 if (!pb_encode_varint(
stream, (pb_uint64_t)size)) {
642 return pb_write(
stream, buffer, size);
651 if (!pb_encode(&substream, fields, src_struct)) {
653 stream->errmsg = substream.errmsg;
658 size = substream.bytes_written;
660 if (!pb_encode_varint(
stream, (pb_uint64_t)size)) {
664 if (
stream->callback == NULL) {
665 return pb_write(
stream, NULL, size);
668 PB_RETURN_ERROR(
stream,
"stream full");
673 substream.callback =
stream->callback;
674 substream.state =
stream->state;
675 substream.max_size = size;
676 substream.bytes_written = 0;
678 substream.errmsg = NULL;
681 status = pb_encode(&substream, fields, src_struct);
683 stream->bytes_written += substream.bytes_written;
684 stream->state = substream.state;
686 stream->errmsg = substream.errmsg;
689 if (substream.bytes_written != size) {
690 PB_RETURN_ERROR(
stream,
"submsg size changed");
699 uint32_t value = safe_read_bool(field->pData) ? 1 : 0;
702 return pb_encode_varint(
stream, value);
706 if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) {
708 pb_uint64_t value = 0;
710 if (field->data_size ==
sizeof(uint_least8_t)) {
711 value = *(
const uint_least8_t *)field->pData;
712 }
else if (field->data_size ==
sizeof(uint_least16_t)) {
713 value = *(
const uint_least16_t *)field->pData;
714 }
else if (field->data_size ==
sizeof(uint32_t)) {
715 value = *(
const uint32_t *)field->pData;
716 }
else if (field->data_size ==
sizeof(pb_uint64_t)) {
717 value = *(
const pb_uint64_t *)field->pData;
719 PB_RETURN_ERROR(
stream,
"invalid data_size");
722 return pb_encode_varint(
stream, value);
725 pb_int64_t value = 0;
727 if (field->data_size ==
sizeof(int_least8_t)) {
728 value = *(
const int_least8_t *)field->pData;
729 }
else if (field->data_size ==
sizeof(int_least16_t)) {
730 value = *(
const int_least16_t *)field->pData;
731 }
else if (field->data_size ==
sizeof(int32_t)) {
732 value = *(
const int32_t *)field->pData;
733 }
else if (field->data_size ==
sizeof(pb_int64_t)) {
734 value = *(
const pb_int64_t *)field->pData;
736 PB_RETURN_ERROR(
stream,
"invalid data_size");
739 if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) {
740 return pb_encode_svarint(
stream, value);
742#ifdef PB_WITHOUT_64BIT
743 else if (value < 0) {
744 return pb_encode_varint_32(
stream, (uint32_t)value, (uint32_t)-1);
748 return pb_encode_varint(
stream, (pb_uint64_t)value);
754#ifdef PB_CONVERT_DOUBLE_FLOAT
755 if (field->data_size ==
sizeof(
float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) {
756 return pb_encode_float_as_double(
stream, *(
float *)field->pData);
760 if (field->data_size ==
sizeof(uint32_t)) {
761 return pb_encode_fixed32(
stream, field->pData);
763#ifndef PB_WITHOUT_64BIT
764 else if (field->data_size ==
sizeof(uint64_t)) {
765 return pb_encode_fixed64(
stream, field->pData);
769 PB_RETURN_ERROR(
stream,
"invalid data_size");
780 return pb_encode_string(
stream, NULL, 0);
783 if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
785 PB_RETURN_ERROR(
stream,
"bytes size exceeded");
788 return pb_encode_string(
stream, bytes->bytes, (
size_t)bytes->size);
793 size_t max_size = (size_t)field->data_size;
794 const char *str = (
const char *)field->pData;
796 if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) {
797 max_size = (size_t)-1;
805 PB_RETURN_ERROR(
stream,
"zero-length string");
818 while (size < max_size && *p !=
'\0') {
824 PB_RETURN_ERROR(
stream,
"unterminated string");
828#ifdef PB_VALIDATE_UTF8
829 if (!pb_validate_utf8(str)) {
830 PB_RETURN_ERROR(
stream,
"invalid utf8");
834 return pb_encode_string(
stream, (
const pb_byte_t *)str, size);
838 if (field->submsg_desc == NULL) {
839 PB_RETURN_ERROR(
stream,
"invalid field descriptor");
842 if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) {
845 if (callback->funcs.encode) {
846 if (!callback->funcs.encode(
stream, field, &callback->arg)) {
852 return pb_encode_submessage(
stream, field->submsg_desc, field->pData);
856 return pb_encode_string(
stream, (
const pb_byte_t *)field->pData, (
size_t)field->data_size);
859#ifdef PB_CONVERT_DOUBLE_FLOAT
861 union {
float f; uint32_t i; } in;
869 sign = (uint_least8_t)((in.i >> 31) & 1);
870 exponent = (int)((in.i >> 23) & 0xFF) - 127;
871 mantissa = in.i & 0x7FFFFF;
873 if (exponent == 128) {
876 }
else if (exponent == -127) {
883 while (!(mantissa & 0x800000)) {
887 mantissa &= 0x7FFFFF;
893 mantissa |= (uint64_t)(exponent + 1023) << 52;
894 mantissa |= (uint64_t)sign << 63;
896 return pb_encode_fixed64(
stream, &mantissa);