Remove useless comparison
[pidgin-git.git] / libpurple / protocols / gg / lib / protobuf-c.c
blob4e16fe1c38eebd55e761ee2008db93097f821133
1 /*
2 * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 /*! \file
31 * Support library for `protoc-c` generated code.
33 * This file implements the public API used by the code generated
34 * by `protoc-c`.
36 * \authors Dave Benson and the protobuf-c authors
38 * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
41 /**
42 * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
43 * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
45 * \todo Use size_t consistently.
48 #include <stdlib.h> /* for malloc, free */
49 #include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
51 /* Pull WORDS_BIGENDIAN etc */
52 #include "config.h"
54 #include "protobuf-c.h"
56 #define TRUE 1
57 #define FALSE 0
59 #define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
61 /* Workaround for Microsoft compilers. */
62 #ifdef _MSC_VER
63 # define inline __inline
64 #endif
66 /**
67 * \defgroup internal Internal functions and macros
69 * These are not exported by the library but are useful to developers working
70 * on `libprotobuf-c` itself.
73 /**
74 * \defgroup macros Utility macros for manipulating structures
76 * Macros and constants used to manipulate the base "classes" generated by
77 * `protobuf-c`. They also define limits and check correctness.
79 * \ingroup internal
80 * @{
83 /** The maximum length of a 64-bit integer in varint encoding. */
84 #define MAX_UINT64_ENCODED_SIZE 10
86 #ifndef PROTOBUF_C_UNPACK_ERROR
87 # define PROTOBUF_C_UNPACK_ERROR(...)
88 #endif
90 /**
91 * Internal `ProtobufCMessage` manipulation macro.
93 * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
94 * STRUCT_MEMBER_PTR().
96 #define STRUCT_MEMBER_P(struct_p, struct_offset) \
97 ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
99 /**
100 * Return field in a `ProtobufCMessage` based on offset.
102 * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
103 * Cast it to the passed type.
105 #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
106 (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
109 * Return field in a `ProtobufCMessage` based on offset.
111 * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
112 * it to a pointer to the passed type.
114 #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
115 ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
117 /* Assertions for magic numbers. */
119 #define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
120 assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
122 #define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
123 assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
125 #define ASSERT_IS_MESSAGE(message) \
126 ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
128 #define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
129 assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
131 /**@}*/
133 /* --- version --- */
135 const char *
136 protobuf_c_version(void)
138 return PROTOBUF_C_VERSION;
141 uint32_t
142 protobuf_c_version_number(void)
144 return PROTOBUF_C_VERSION_NUMBER;
147 /* --- allocator --- */
149 static void *
150 system_alloc(void *allocator_data, size_t size)
152 return malloc(size);
155 static void
156 system_free(void *allocator_data, void *data)
158 free(data);
161 static inline void *
162 do_alloc(ProtobufCAllocator *allocator, size_t size)
164 return allocator->alloc(allocator->allocator_data, size);
167 static inline void
168 do_free(ProtobufCAllocator *allocator, void *data)
170 if (data != NULL)
171 allocator->free(allocator->allocator_data, data);
175 * This allocator uses the system's malloc() and free(). It is the default
176 * allocator used if NULL is passed as the ProtobufCAllocator to an exported
177 * function.
179 static ProtobufCAllocator protobuf_c__allocator = {
180 .alloc = &system_alloc,
181 .free = &system_free,
182 .allocator_data = NULL,
185 /* === buffer-simple === */
187 void
188 protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
189 size_t len, const uint8_t *data)
191 ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
192 size_t new_len = simp->len + len;
194 if (new_len > simp->alloced) {
195 ProtobufCAllocator *allocator = simp->allocator;
196 size_t new_alloced = simp->alloced * 2;
197 uint8_t *new_data;
199 if (allocator == NULL)
200 allocator = &protobuf_c__allocator;
201 while (new_alloced < new_len)
202 new_alloced += new_alloced;
203 new_data = do_alloc(allocator, new_alloced);
204 if (!new_data)
205 return;
206 memcpy(new_data, simp->data, simp->len);
207 if (simp->must_free_data)
208 do_free(allocator, simp->data);
209 else
210 simp->must_free_data = TRUE;
211 simp->data = new_data;
212 simp->alloced = new_alloced;
214 memcpy(simp->data + simp->len, data, len);
215 simp->len = new_len;
219 * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
221 * Routines mainly used by protobuf_c_message_get_packed_size().
223 * \ingroup internal
224 * @{
228 * Return the number of bytes required to store the tag for the field. Includes
229 * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
231 * \param number
232 * Field tag to encode.
233 * \return
234 * Number of bytes required.
236 static inline size_t
237 get_tag_size(unsigned number)
239 if (number < (1 << 4)) {
240 return 1;
241 } else if (number < (1 << 11)) {
242 return 2;
243 } else if (number < (1 << 18)) {
244 return 3;
245 } else if (number < (1 << 25)) {
246 return 4;
247 } else {
248 return 5;
253 * Return the number of bytes required to store a variable-length unsigned
254 * 32-bit integer in base-128 varint encoding.
256 * \param v
257 * Value to encode.
258 * \return
259 * Number of bytes required.
261 static inline size_t
262 uint32_size(uint32_t v)
264 if (v < (1 << 7)) {
265 return 1;
266 } else if (v < (1 << 14)) {
267 return 2;
268 } else if (v < (1 << 21)) {
269 return 3;
270 } else if (v < (1 << 28)) {
271 return 4;
272 } else {
273 return 5;
278 * Return the number of bytes required to store a variable-length signed 32-bit
279 * integer in base-128 varint encoding.
281 * \param v
282 * Value to encode.
283 * \return
284 * Number of bytes required.
286 static inline size_t
287 int32_size(int32_t v)
289 if (v < 0) {
290 return 10;
291 } else if (v < (1 << 7)) {
292 return 1;
293 } else if (v < (1 << 14)) {
294 return 2;
295 } else if (v < (1 << 21)) {
296 return 3;
297 } else if (v < (1 << 28)) {
298 return 4;
299 } else {
300 return 5;
305 * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
306 * integer.
308 * \param v
309 * Value to encode.
310 * \return
311 * ZigZag encoded integer.
313 static inline uint32_t
314 zigzag32(int32_t v)
316 if (v < 0)
317 return ((uint32_t) (-v)) * 2 - 1;
318 else
319 return v * 2;
323 * Return the number of bytes required to store a signed 32-bit integer,
324 * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
325 * varint encoding.
327 * \param v
328 * Value to encode.
329 * \return
330 * Number of bytes required.
332 static inline size_t
333 sint32_size(int32_t v)
335 return uint32_size(zigzag32(v));
339 * Return the number of bytes required to store a 64-bit unsigned integer in
340 * base-128 varint encoding.
342 * \param v
343 * Value to encode.
344 * \return
345 * Number of bytes required.
347 static inline size_t
348 uint64_size(uint64_t v)
350 uint32_t upper_v = (uint32_t) (v >> 32);
352 if (upper_v == 0) {
353 return uint32_size((uint32_t) v);
354 } else if (upper_v < (1 << 3)) {
355 return 5;
356 } else if (upper_v < (1 << 10)) {
357 return 6;
358 } else if (upper_v < (1 << 17)) {
359 return 7;
360 } else if (upper_v < (1 << 24)) {
361 return 8;
362 } else if (upper_v < (1U << 31)) {
363 return 9;
364 } else {
365 return 10;
370 * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
371 * integer.
373 * \param v
374 * Value to encode.
375 * \return
376 * ZigZag encoded integer.
378 static inline uint64_t
379 zigzag64(int64_t v)
381 if (v < 0)
382 return ((uint64_t) (-v)) * 2 - 1;
383 else
384 return v * 2;
388 * Return the number of bytes required to store a signed 64-bit integer,
389 * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
390 * varint encoding.
392 * \param v
393 * Value to encode.
394 * \return
395 * Number of bytes required.
397 static inline size_t
398 sint64_size(int64_t v)
400 return uint64_size(zigzag64(v));
404 * Calculate the serialized size of a single required message field, including
405 * the space needed by the preceding tag.
407 * \param field
408 * Field descriptor for member.
409 * \param member
410 * Field to encode.
411 * \return
412 * Number of bytes required.
414 static size_t
415 required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
416 const void *member)
418 size_t rv = get_tag_size(field->id);
420 switch (field->type) {
421 case PROTOBUF_C_TYPE_SINT32:
422 return rv + sint32_size(*(const int32_t *) member);
423 case PROTOBUF_C_TYPE_INT32:
424 return rv + int32_size(*(const uint32_t *) member);
425 case PROTOBUF_C_TYPE_UINT32:
426 return rv + uint32_size(*(const uint32_t *) member);
427 case PROTOBUF_C_TYPE_SINT64:
428 return rv + sint64_size(*(const int64_t *) member);
429 case PROTOBUF_C_TYPE_INT64:
430 case PROTOBUF_C_TYPE_UINT64:
431 return rv + uint64_size(*(const uint64_t *) member);
432 case PROTOBUF_C_TYPE_SFIXED32:
433 case PROTOBUF_C_TYPE_FIXED32:
434 return rv + 4;
435 case PROTOBUF_C_TYPE_SFIXED64:
436 case PROTOBUF_C_TYPE_FIXED64:
437 return rv + 8;
438 case PROTOBUF_C_TYPE_BOOL:
439 return rv + 1;
440 case PROTOBUF_C_TYPE_FLOAT:
441 return rv + 4;
442 case PROTOBUF_C_TYPE_DOUBLE:
443 return rv + 8;
444 case PROTOBUF_C_TYPE_ENUM:
445 /* \todo Is this correct for negative-valued enums? */
446 return rv + uint32_size(*(const uint32_t *) member);
447 case PROTOBUF_C_TYPE_STRING: {
448 const char *str = *(char * const *) member;
449 size_t len = str ? strlen(str) : 0;
450 return rv + uint32_size(len) + len;
452 case PROTOBUF_C_TYPE_BYTES: {
453 size_t len = ((const ProtobufCBinaryData *) member)->len;
454 return rv + uint32_size(len) + len;
456 case PROTOBUF_C_TYPE_MESSAGE: {
457 const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
458 size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
459 return rv + uint32_size(subrv) + subrv;
462 PROTOBUF_C__ASSERT_NOT_REACHED();
463 return 0;
467 * Calculate the serialized size of a single optional message field, including
468 * the space needed by the preceding tag. Returns 0 if the optional field isn't
469 * set.
471 * \param field
472 * Field descriptor for member.
473 * \param has
474 * True if the field exists, false if not.
475 * \param member
476 * Field to encode.
477 * \return
478 * Number of bytes required.
480 static size_t
481 optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
482 const protobuf_c_boolean *has,
483 const void *member)
485 if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
486 field->type == PROTOBUF_C_TYPE_STRING)
488 const void *ptr = *(const void * const *) member;
489 if (ptr == NULL || ptr == field->default_value)
490 return 0;
491 } else {
492 if (!*has)
493 return 0;
495 return required_field_get_packed_size(field, member);
499 * Calculate the serialized size of repeated message fields, which may consist
500 * of any number of values (including 0). Includes the space needed by the
501 * preceding tags (as needed).
503 * \param field
504 * Field descriptor for member.
505 * \param count
506 * Number of repeated field members.
507 * \param member
508 * Field to encode.
509 * \return
510 * Number of bytes required.
512 static size_t
513 repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
514 size_t count, const void *member)
516 size_t header_size;
517 size_t rv = 0;
518 unsigned i;
519 void *array = *(void * const *) member;
521 if (count == 0)
522 return 0;
523 header_size = get_tag_size(field->id);
524 if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
525 header_size *= count;
527 switch (field->type) {
528 case PROTOBUF_C_TYPE_SINT32:
529 for (i = 0; i < count; i++)
530 rv += sint32_size(((int32_t *) array)[i]);
531 break;
532 case PROTOBUF_C_TYPE_INT32:
533 for (i = 0; i < count; i++)
534 rv += int32_size(((uint32_t *) array)[i]);
535 break;
536 case PROTOBUF_C_TYPE_UINT32:
537 case PROTOBUF_C_TYPE_ENUM:
538 for (i = 0; i < count; i++)
539 rv += uint32_size(((uint32_t *) array)[i]);
540 break;
541 case PROTOBUF_C_TYPE_SINT64:
542 for (i = 0; i < count; i++)
543 rv += sint64_size(((int64_t *) array)[i]);
544 break;
545 case PROTOBUF_C_TYPE_INT64:
546 case PROTOBUF_C_TYPE_UINT64:
547 for (i = 0; i < count; i++)
548 rv += uint64_size(((uint64_t *) array)[i]);
549 break;
550 case PROTOBUF_C_TYPE_SFIXED32:
551 case PROTOBUF_C_TYPE_FIXED32:
552 case PROTOBUF_C_TYPE_FLOAT:
553 rv += 4 * count;
554 break;
555 case PROTOBUF_C_TYPE_SFIXED64:
556 case PROTOBUF_C_TYPE_FIXED64:
557 case PROTOBUF_C_TYPE_DOUBLE:
558 rv += 8 * count;
559 break;
560 case PROTOBUF_C_TYPE_BOOL:
561 rv += count;
562 break;
563 case PROTOBUF_C_TYPE_STRING:
564 for (i = 0; i < count; i++) {
565 size_t len = strlen(((char **) array)[i]);
566 rv += uint32_size(len) + len;
568 break;
569 case PROTOBUF_C_TYPE_BYTES:
570 for (i = 0; i < count; i++) {
571 size_t len = ((ProtobufCBinaryData *) array)[i].len;
572 rv += uint32_size(len) + len;
574 break;
575 case PROTOBUF_C_TYPE_MESSAGE:
576 for (i = 0; i < count; i++) {
577 size_t len = protobuf_c_message_get_packed_size(
578 ((ProtobufCMessage **) array)[i]);
579 rv += uint32_size(len) + len;
581 break;
584 if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
585 header_size += uint32_size(rv);
586 return header_size + rv;
590 * Calculate the serialized size of an unknown field, i.e. one that is passed
591 * through mostly uninterpreted. This is required for forward compatibility if
592 * new fields are added to the message descriptor.
594 * \param field
595 * Unknown field type.
596 * \return
597 * Number of bytes required.
599 static inline size_t
600 unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
602 return get_tag_size(field->tag) + field->len;
605 /**@}*/
608 * Calculate the serialized size of the message.
610 size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
612 unsigned i;
613 size_t rv = 0;
615 ASSERT_IS_MESSAGE(message);
616 for (i = 0; i < message->descriptor->n_fields; i++) {
617 const ProtobufCFieldDescriptor *field =
618 message->descriptor->fields + i;
619 const void *member =
620 ((const char *) message) + field->offset;
621 const void *qmember =
622 ((const char *) message) + field->quantifier_offset;
624 if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
625 rv += required_field_get_packed_size(field, member);
626 } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
627 rv += optional_field_get_packed_size(field, qmember, member);
628 } else {
629 rv += repeated_field_get_packed_size(
630 field,
631 *(const size_t *) qmember,
632 member
636 for (i = 0; i < message->n_unknown_fields; i++)
637 rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
638 return rv;
642 * \defgroup pack protobuf_c_message_pack() implementation
644 * Routines mainly used by protobuf_c_message_pack().
646 * \ingroup internal
647 * @{
651 * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
652 * number of bytes written, which must be 5 or less.
654 * \param value
655 * Value to encode.
656 * \param[out] out
657 * Packed value.
658 * \return
659 * Number of bytes written to `out`.
661 static inline size_t
662 uint32_pack(uint32_t value, uint8_t *out)
664 unsigned rv = 0;
666 if (value >= 0x80) {
667 out[rv++] = value | 0x80;
668 value >>= 7;
669 if (value >= 0x80) {
670 out[rv++] = value | 0x80;
671 value >>= 7;
672 if (value >= 0x80) {
673 out[rv++] = value | 0x80;
674 value >>= 7;
675 if (value >= 0x80) {
676 out[rv++] = value | 0x80;
677 value >>= 7;
682 /* assert: value<128 */
683 out[rv++] = value;
684 return rv;
688 * Pack a signed 32-bit integer and return the number of bytes written.
689 * Negative numbers are encoded as two's complement 64-bit integers.
691 * \param value
692 * Value to encode.
693 * \param[out] out
694 * Packed value.
695 * \return
696 * Number of bytes written to `out`.
698 static inline size_t
699 int32_pack(int32_t value, uint8_t *out)
701 if (value < 0) {
702 out[0] = value | 0x80;
703 out[1] = (value >> 7) | 0x80;
704 out[2] = (value >> 14) | 0x80;
705 out[3] = (value >> 21) | 0x80;
706 out[4] = (value >> 28) | 0x80;
707 out[5] = out[6] = out[7] = out[8] = 0xff;
708 out[9] = 0x01;
709 return 10;
710 } else {
711 return uint32_pack(value, out);
716 * Pack a signed 32-bit integer using ZigZag encoding and return the number of
717 * bytes written.
719 * \param value
720 * Value to encode.
721 * \param[out] out
722 * Packed value.
723 * \return
724 * Number of bytes written to `out`.
726 static inline size_t
727 sint32_pack(int32_t value, uint8_t *out)
729 return uint32_pack(zigzag32(value), out);
733 * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
734 * number of bytes written.
736 * \param value
737 * Value to encode.
738 * \param[out] out
739 * Packed value.
740 * \return
741 * Number of bytes written to `out`.
743 static size_t
744 uint64_pack(uint64_t value, uint8_t *out)
746 uint32_t hi = (uint32_t) (value >> 32);
747 uint32_t lo = (uint32_t) value;
748 unsigned rv;
750 if (hi == 0)
751 return uint32_pack((uint32_t) lo, out);
752 out[0] = (lo) | 0x80;
753 out[1] = (lo >> 7) | 0x80;
754 out[2] = (lo >> 14) | 0x80;
755 out[3] = (lo >> 21) | 0x80;
756 if (hi < 8) {
757 out[4] = (hi << 4) | (lo >> 28);
758 return 5;
759 } else {
760 out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
761 hi >>= 3;
763 rv = 5;
764 while (hi >= 128) {
765 out[rv++] = hi | 0x80;
766 hi >>= 7;
768 out[rv++] = hi;
769 return rv;
773 * Pack a 64-bit signed integer in ZigZag encoding and return the number of
774 * bytes written.
776 * \param value
777 * Value to encode.
778 * \param[out] out
779 * Packed value.
780 * \return
781 * Number of bytes written to `out`.
783 static inline size_t
784 sint64_pack(int64_t value, uint8_t *out)
786 return uint64_pack(zigzag64(value), out);
790 * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
791 * types fixed32, sfixed32, float. Similar to "htole32".
793 * \param value
794 * Value to encode.
795 * \param[out] out
796 * Packed value.
797 * \return
798 * Number of bytes written to `out`.
800 static inline size_t
801 fixed32_pack(uint32_t value, void *out)
803 #if !defined(WORDS_BIGENDIAN)
804 memcpy(out, &value, 4);
805 #else
806 uint8_t *buf = out;
808 buf[0] = value;
809 buf[1] = value >> 8;
810 buf[2] = value >> 16;
811 buf[3] = value >> 24;
812 #endif
813 return 4;
817 * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
818 * types fixed64, sfixed64, double. Similar to "htole64".
820 * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
821 * version would be appreciated, plus a way to decide to use 64-bit math where
822 * convenient.
824 * \param value
825 * Value to encode.
826 * \param[out] out
827 * Packed value.
828 * \return
829 * Number of bytes written to `out`.
831 static inline size_t
832 fixed64_pack(uint64_t value, void *out)
834 #if !defined(WORDS_BIGENDIAN)
835 memcpy(out, &value, 8);
836 #else
837 fixed32_pack(value, out);
838 fixed32_pack(value >> 32, ((char *) out) + 4);
839 #endif
840 return 8;
844 * Pack a boolean value as an integer and return the number of bytes written.
846 * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
847 * that is idiomatic C++ in some STL implementations.
849 * \param value
850 * Value to encode.
851 * \param[out] out
852 * Packed value.
853 * \return
854 * Number of bytes written to `out`.
856 static inline size_t
857 boolean_pack(protobuf_c_boolean value, uint8_t *out)
859 *out = value ? TRUE : FALSE;
860 return 1;
864 * Pack a NUL-terminated C string and return the number of bytes written. The
865 * output includes a length delimiter.
867 * The NULL pointer is treated as an empty string. This isn't really necessary,
868 * but it allows people to leave required strings blank. (See Issue #13 in the
869 * bug tracker for a little more explanation).
871 * \param str
872 * String to encode.
873 * \param[out] out
874 * Packed value.
875 * \return
876 * Number of bytes written to `out`.
878 static inline size_t
879 string_pack(const char *str, uint8_t *out)
881 if (str == NULL) {
882 out[0] = 0;
883 return 1;
884 } else {
885 size_t len = strlen(str);
886 size_t rv = uint32_pack(len, out);
887 memcpy(out + rv, str, len);
888 return rv + len;
893 * Pack a ProtobufCBinaryData and return the number of bytes written. The output
894 * includes a length delimiter.
896 * \param bd
897 * ProtobufCBinaryData to encode.
898 * \param[out] out
899 * Packed value.
900 * \return
901 * Number of bytes written to `out`.
903 static inline size_t
904 binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
906 size_t len = bd->len;
907 size_t rv = uint32_pack(len, out);
908 memcpy(out + rv, bd->data, len);
909 return rv + len;
913 * Pack a ProtobufCMessage and return the number of bytes written. The output
914 * includes a length delimiter.
916 * \param message
917 * ProtobufCMessage object to pack.
918 * \param[out] out
919 * Packed message.
920 * \return
921 * Number of bytes written to `out`.
923 static inline size_t
924 prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
926 if (message == NULL) {
927 out[0] = 0;
928 return 1;
929 } else {
930 size_t rv = protobuf_c_message_pack(message, out + 1);
931 uint32_t rv_packed_size = uint32_size(rv);
932 if (rv_packed_size != 1)
933 memmove(out + rv_packed_size, out + 1, rv);
934 return uint32_pack(rv, out) + rv;
939 * Pack a field tag.
941 * Wire-type will be added in required_field_pack().
943 * \todo Just call uint64_pack on 64-bit platforms.
945 * \param id
946 * Tag value to encode.
947 * \param[out] out
948 * Packed value.
949 * \return
950 * Number of bytes written to `out`.
952 static size_t
953 tag_pack(uint32_t id, uint8_t *out)
955 if (id < (1 << (32 - 3)))
956 return uint32_pack(id << 3, out);
957 else
958 return uint64_pack(((uint64_t) id) << 3, out);
962 * Pack a required field and return the number of bytes written.
964 * \param field
965 * Field descriptor.
966 * \param member
967 * The field member.
968 * \param[out] out
969 * Packed value.
970 * \return
971 * Number of bytes written to `out`.
973 static size_t
974 required_field_pack(const ProtobufCFieldDescriptor *field,
975 const void *member, uint8_t *out)
977 size_t rv = tag_pack(field->id, out);
979 switch (field->type) {
980 case PROTOBUF_C_TYPE_SINT32:
981 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
982 return rv + sint32_pack(*(const int32_t *) member, out + rv);
983 case PROTOBUF_C_TYPE_INT32:
984 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
985 return rv + int32_pack(*(const uint32_t *) member, out + rv);
986 case PROTOBUF_C_TYPE_UINT32:
987 case PROTOBUF_C_TYPE_ENUM:
988 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
989 return rv + uint32_pack(*(const uint32_t *) member, out + rv);
990 case PROTOBUF_C_TYPE_SINT64:
991 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
992 return rv + sint64_pack(*(const int64_t *) member, out + rv);
993 case PROTOBUF_C_TYPE_INT64:
994 case PROTOBUF_C_TYPE_UINT64:
995 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
996 return rv + uint64_pack(*(const uint64_t *) member, out + rv);
997 case PROTOBUF_C_TYPE_SFIXED32:
998 case PROTOBUF_C_TYPE_FIXED32:
999 case PROTOBUF_C_TYPE_FLOAT:
1000 out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1001 return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
1002 case PROTOBUF_C_TYPE_SFIXED64:
1003 case PROTOBUF_C_TYPE_FIXED64:
1004 case PROTOBUF_C_TYPE_DOUBLE:
1005 out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1006 return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
1007 case PROTOBUF_C_TYPE_BOOL:
1008 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1009 return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
1010 case PROTOBUF_C_TYPE_STRING:
1011 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1012 return rv + string_pack(*(char *const *) member, out + rv);
1013 case PROTOBUF_C_TYPE_BYTES:
1014 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1015 return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
1016 case PROTOBUF_C_TYPE_MESSAGE:
1017 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1018 return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
1020 PROTOBUF_C__ASSERT_NOT_REACHED();
1021 return 0;
1025 * Pack an optional field and return the number of bytes written.
1027 * \param field
1028 * Field descriptor.
1029 * \param has
1030 * Whether the field is set.
1031 * \param member
1032 * The field member.
1033 * \param[out] out
1034 * Packed value.
1035 * \return
1036 * Number of bytes written to `out`.
1038 static size_t
1039 optional_field_pack(const ProtobufCFieldDescriptor *field,
1040 const protobuf_c_boolean *has,
1041 const void *member, uint8_t *out)
1043 if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1044 field->type == PROTOBUF_C_TYPE_STRING)
1046 const void *ptr = *(const void * const *) member;
1047 if (ptr == NULL || ptr == field->default_value)
1048 return 0;
1049 } else {
1050 if (!*has)
1051 return 0;
1053 return required_field_pack(field, member, out);
1057 * Given a field type, return the in-memory size.
1059 * \todo Implement as a table lookup.
1061 * \param type
1062 * Field type.
1063 * \return
1064 * Size of the field.
1066 static inline size_t
1067 sizeof_elt_in_repeated_array(ProtobufCType type)
1069 switch (type) {
1070 case PROTOBUF_C_TYPE_SINT32:
1071 case PROTOBUF_C_TYPE_INT32:
1072 case PROTOBUF_C_TYPE_UINT32:
1073 case PROTOBUF_C_TYPE_SFIXED32:
1074 case PROTOBUF_C_TYPE_FIXED32:
1075 case PROTOBUF_C_TYPE_FLOAT:
1076 case PROTOBUF_C_TYPE_ENUM:
1077 return 4;
1078 case PROTOBUF_C_TYPE_SINT64:
1079 case PROTOBUF_C_TYPE_INT64:
1080 case PROTOBUF_C_TYPE_UINT64:
1081 case PROTOBUF_C_TYPE_SFIXED64:
1082 case PROTOBUF_C_TYPE_FIXED64:
1083 case PROTOBUF_C_TYPE_DOUBLE:
1084 return 8;
1085 case PROTOBUF_C_TYPE_BOOL:
1086 return sizeof(protobuf_c_boolean);
1087 case PROTOBUF_C_TYPE_STRING:
1088 case PROTOBUF_C_TYPE_MESSAGE:
1089 return sizeof(void *);
1090 case PROTOBUF_C_TYPE_BYTES:
1091 return sizeof(ProtobufCBinaryData);
1093 PROTOBUF_C__ASSERT_NOT_REACHED();
1094 return 0;
1098 * Pack an array of 32-bit quantities.
1100 * \param[out] out
1101 * Destination.
1102 * \param[in] in
1103 * Source.
1104 * \param[in] n
1105 * Number of elements in the source array.
1107 static void
1108 copy_to_little_endian_32(void *out, const void *in, const unsigned n)
1110 #if !defined(WORDS_BIGENDIAN)
1111 memcpy(out, in, n * 4);
1112 #else
1113 unsigned i;
1114 const uint32_t *ini = in;
1115 for (i = 0; i < n; i++)
1116 fixed32_pack(ini[i], (uint32_t *) out + i);
1117 #endif
1121 * Pack an array of 64-bit quantities.
1123 * \param[out] out
1124 * Destination.
1125 * \param[in] in
1126 * Source.
1127 * \param[in] n
1128 * Number of elements in the source array.
1130 static void
1131 copy_to_little_endian_64(void *out, const void *in, const unsigned n)
1133 #if !defined(WORDS_BIGENDIAN)
1134 memcpy(out, in, n * 8);
1135 #else
1136 unsigned i;
1137 const uint64_t *ini = in;
1138 for (i = 0; i < n; i++)
1139 fixed64_pack(ini[i], (uint64_t *) out + i);
1140 #endif
1144 * Get the minimum number of bytes required to pack a field value of a
1145 * particular type.
1147 * \param type
1148 * Field type.
1149 * \return
1150 * Number of bytes.
1152 static unsigned
1153 get_type_min_size(ProtobufCType type)
1155 if (type == PROTOBUF_C_TYPE_SFIXED32 ||
1156 type == PROTOBUF_C_TYPE_FIXED32 ||
1157 type == PROTOBUF_C_TYPE_FLOAT)
1159 return 4;
1161 if (type == PROTOBUF_C_TYPE_SFIXED64 ||
1162 type == PROTOBUF_C_TYPE_FIXED64 ||
1163 type == PROTOBUF_C_TYPE_DOUBLE)
1165 return 8;
1167 return 1;
1171 * Packs the elements of a repeated field and returns the serialised field and
1172 * its length.
1174 * \param field
1175 * Field descriptor.
1176 * \param count
1177 * Number of elements in the repeated field array.
1178 * \param member
1179 * Pointer to the elements for this repeated field.
1180 * \param[out] out
1181 * Serialised representation of the repeated field.
1182 * \return
1183 * Number of bytes serialised to `out`.
1185 static size_t
1186 repeated_field_pack(const ProtobufCFieldDescriptor *field,
1187 size_t count, const void *member, uint8_t *out)
1189 void *array = *(void * const *) member;
1190 unsigned i;
1192 if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1193 unsigned header_len;
1194 unsigned len_start;
1195 unsigned min_length;
1196 unsigned payload_len;
1197 unsigned length_size_min;
1198 unsigned actual_length_size;
1199 uint8_t *payload_at;
1201 if (count == 0)
1202 return 0;
1203 header_len = tag_pack(field->id, out);
1204 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1205 len_start = header_len;
1206 min_length = get_type_min_size(field->type) * count;
1207 length_size_min = uint32_size(min_length);
1208 header_len += length_size_min;
1209 payload_at = out + header_len;
1211 switch (field->type) {
1212 case PROTOBUF_C_TYPE_SFIXED32:
1213 case PROTOBUF_C_TYPE_FIXED32:
1214 case PROTOBUF_C_TYPE_FLOAT:
1215 copy_to_little_endian_32(payload_at, array, count);
1216 payload_at += count * 4;
1217 break;
1218 case PROTOBUF_C_TYPE_SFIXED64:
1219 case PROTOBUF_C_TYPE_FIXED64:
1220 case PROTOBUF_C_TYPE_DOUBLE:
1221 copy_to_little_endian_64(payload_at, array, count);
1222 payload_at += count * 8;
1223 break;
1224 case PROTOBUF_C_TYPE_INT32: {
1225 const int32_t *arr = (const int32_t *) array;
1226 for (i = 0; i < count; i++)
1227 payload_at += int32_pack(arr[i], payload_at);
1228 break;
1230 case PROTOBUF_C_TYPE_SINT32: {
1231 const int32_t *arr = (const int32_t *) array;
1232 for (i = 0; i < count; i++)
1233 payload_at += sint32_pack(arr[i], payload_at);
1234 break;
1236 case PROTOBUF_C_TYPE_SINT64: {
1237 const int64_t *arr = (const int64_t *) array;
1238 for (i = 0; i < count; i++)
1239 payload_at += sint64_pack(arr[i], payload_at);
1240 break;
1242 case PROTOBUF_C_TYPE_ENUM:
1243 case PROTOBUF_C_TYPE_UINT32: {
1244 const uint32_t *arr = (const uint32_t *) array;
1245 for (i = 0; i < count; i++)
1246 payload_at += uint32_pack(arr[i], payload_at);
1247 break;
1249 case PROTOBUF_C_TYPE_INT64:
1250 case PROTOBUF_C_TYPE_UINT64: {
1251 const uint64_t *arr = (const uint64_t *) array;
1252 for (i = 0; i < count; i++)
1253 payload_at += uint64_pack(arr[i], payload_at);
1254 break;
1256 case PROTOBUF_C_TYPE_BOOL: {
1257 const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
1258 for (i = 0; i < count; i++)
1259 payload_at += boolean_pack(arr[i], payload_at);
1260 break;
1262 default:
1263 PROTOBUF_C__ASSERT_NOT_REACHED();
1266 payload_len = payload_at - (out + header_len);
1267 actual_length_size = uint32_size(payload_len);
1268 if (length_size_min != actual_length_size) {
1269 assert(actual_length_size == length_size_min + 1);
1270 memmove(out + header_len + 1, out + header_len,
1271 payload_len);
1272 header_len++;
1274 uint32_pack(payload_len, out + len_start);
1275 return header_len + payload_len;
1276 } else {
1277 /* not "packed" cased */
1278 /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1279 size_t rv = 0;
1280 unsigned siz = sizeof_elt_in_repeated_array(field->type);
1282 for (i = 0; i < count; i++) {
1283 rv += required_field_pack(field, array, out + rv);
1284 array = (char *)array + siz;
1286 return rv;
1290 static size_t
1291 unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
1293 size_t rv = tag_pack(field->tag, out);
1294 out[0] |= field->wire_type;
1295 memcpy(out + rv, field->data, field->len);
1296 return rv + field->len;
1299 /**@}*/
1301 size_t
1302 protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
1304 unsigned i;
1305 size_t rv = 0;
1307 ASSERT_IS_MESSAGE(message);
1308 for (i = 0; i < message->descriptor->n_fields; i++) {
1309 const ProtobufCFieldDescriptor *field =
1310 message->descriptor->fields + i;
1311 const void *member = ((const char *) message) + field->offset;
1314 * It doesn't hurt to compute qmember (a pointer to the
1315 * quantifier field of the structure), but the pointer is only
1316 * valid if the field is:
1317 * - a repeated field, or
1318 * - an optional field that isn't a pointer type
1319 * (Meaning: not a message or a string).
1321 const void *qmember =
1322 ((const char *) message) + field->quantifier_offset;
1324 if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1325 rv += required_field_pack(field, member, out + rv);
1326 } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1328 * Note that qmember is bogus for strings and messages,
1329 * but it isn't used.
1331 rv += optional_field_pack(field, qmember, member, out + rv);
1332 } else {
1333 rv += repeated_field_pack(field, *(const size_t *) qmember,
1334 member, out + rv);
1337 for (i = 0; i < message->n_unknown_fields; i++)
1338 rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
1339 return rv;
1343 * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
1345 * Routines mainly used by protobuf_c_message_pack_to_buffer().
1347 * \ingroup internal
1348 * @{
1352 * Pack a required field to a virtual buffer.
1354 * \param field
1355 * Field descriptor.
1356 * \param member
1357 * The element to be packed.
1358 * \param[out] buffer
1359 * Virtual buffer to append data to.
1360 * \return
1361 * Number of bytes packed.
1363 static size_t
1364 required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1365 const void *member, ProtobufCBuffer *buffer)
1367 size_t rv;
1368 uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1370 rv = tag_pack(field->id, scratch);
1371 switch (field->type) {
1372 case PROTOBUF_C_TYPE_SINT32:
1373 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1374 rv += sint32_pack(*(const int32_t *) member, scratch + rv);
1375 buffer->append(buffer, rv, scratch);
1376 break;
1377 case PROTOBUF_C_TYPE_INT32:
1378 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1379 rv += int32_pack(*(const uint32_t *) member, scratch + rv);
1380 buffer->append(buffer, rv, scratch);
1381 break;
1382 case PROTOBUF_C_TYPE_UINT32:
1383 case PROTOBUF_C_TYPE_ENUM:
1384 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1385 rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
1386 buffer->append(buffer, rv, scratch);
1387 break;
1388 case PROTOBUF_C_TYPE_SINT64:
1389 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1390 rv += sint64_pack(*(const int64_t *) member, scratch + rv);
1391 buffer->append(buffer, rv, scratch);
1392 break;
1393 case PROTOBUF_C_TYPE_INT64:
1394 case PROTOBUF_C_TYPE_UINT64:
1395 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1396 rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
1397 buffer->append(buffer, rv, scratch);
1398 break;
1399 case PROTOBUF_C_TYPE_SFIXED32:
1400 case PROTOBUF_C_TYPE_FIXED32:
1401 case PROTOBUF_C_TYPE_FLOAT:
1402 scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1403 rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
1404 buffer->append(buffer, rv, scratch);
1405 break;
1406 case PROTOBUF_C_TYPE_SFIXED64:
1407 case PROTOBUF_C_TYPE_FIXED64:
1408 case PROTOBUF_C_TYPE_DOUBLE:
1409 scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1410 rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
1411 buffer->append(buffer, rv, scratch);
1412 break;
1413 case PROTOBUF_C_TYPE_BOOL:
1414 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1415 rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
1416 buffer->append(buffer, rv, scratch);
1417 break;
1418 case PROTOBUF_C_TYPE_STRING: {
1419 const char *str = *(char *const *) member;
1420 size_t sublen = str ? strlen(str) : 0;
1422 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1423 rv += uint32_pack(sublen, scratch + rv);
1424 buffer->append(buffer, rv, scratch);
1425 buffer->append(buffer, sublen, (const uint8_t *) str);
1426 rv += sublen;
1427 break;
1429 case PROTOBUF_C_TYPE_BYTES: {
1430 const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
1431 size_t sublen = bd->len;
1433 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1434 rv += uint32_pack(sublen, scratch + rv);
1435 buffer->append(buffer, rv, scratch);
1436 buffer->append(buffer, sublen, bd->data);
1437 rv += sublen;
1438 break;
1440 case PROTOBUF_C_TYPE_MESSAGE: {
1441 uint8_t simple_buffer_scratch[256];
1442 size_t sublen;
1443 const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1444 ProtobufCBufferSimple simple_buffer =
1445 PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
1447 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1448 if (msg == NULL)
1449 sublen = 0;
1450 else
1451 sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
1452 rv += uint32_pack(sublen, scratch + rv);
1453 buffer->append(buffer, rv, scratch);
1454 buffer->append(buffer, sublen, simple_buffer.data);
1455 rv += sublen;
1456 PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
1457 break;
1459 default:
1460 PROTOBUF_C__ASSERT_NOT_REACHED();
1462 return rv;
1466 * Pack an optional field to a buffer.
1468 * \param field
1469 * Field descriptor.
1470 * \param has
1471 * Whether the field is set.
1472 * \param member
1473 * The element to be packed.
1474 * \param[out] buffer
1475 * Virtual buffer to append data to.
1476 * \return
1477 * Number of bytes serialised to `buffer`.
1479 static size_t
1480 optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1481 const protobuf_c_boolean *has,
1482 const void *member, ProtobufCBuffer *buffer)
1484 if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1485 field->type == PROTOBUF_C_TYPE_STRING)
1487 const void *ptr = *(const void *const *) member;
1488 if (ptr == NULL || ptr == field->default_value)
1489 return 0;
1490 } else {
1491 if (!*has)
1492 return 0;
1494 return required_field_pack_to_buffer(field, member, buffer);
1498 * Get the packed size of an array of same field type.
1500 * \param field
1501 * Field descriptor.
1502 * \param count
1503 * Number of elements of this type.
1504 * \param array
1505 * The elements to get the size of.
1506 * \return
1507 * Number of bytes required.
1509 static size_t
1510 get_packed_payload_length(const ProtobufCFieldDescriptor *field,
1511 unsigned count, const void *array)
1513 unsigned rv = 0;
1514 unsigned i;
1516 switch (field->type) {
1517 case PROTOBUF_C_TYPE_SFIXED32:
1518 case PROTOBUF_C_TYPE_FIXED32:
1519 case PROTOBUF_C_TYPE_FLOAT:
1520 return count * 4;
1521 case PROTOBUF_C_TYPE_SFIXED64:
1522 case PROTOBUF_C_TYPE_FIXED64:
1523 case PROTOBUF_C_TYPE_DOUBLE:
1524 return count * 8;
1525 case PROTOBUF_C_TYPE_INT32: {
1526 const int32_t *arr = (const int32_t *) array;
1527 for (i = 0; i < count; i++)
1528 rv += int32_size(arr[i]);
1529 break;
1531 case PROTOBUF_C_TYPE_SINT32: {
1532 const int32_t *arr = (const int32_t *) array;
1533 for (i = 0; i < count; i++)
1534 rv += sint32_size(arr[i]);
1535 break;
1537 case PROTOBUF_C_TYPE_ENUM:
1538 case PROTOBUF_C_TYPE_UINT32: {
1539 const uint32_t *arr = (const uint32_t *) array;
1540 for (i = 0; i < count; i++)
1541 rv += uint32_size(arr[i]);
1542 break;
1544 case PROTOBUF_C_TYPE_SINT64: {
1545 const int64_t *arr = (const int64_t *) array;
1546 for (i = 0; i < count; i++)
1547 rv += sint64_size(arr[i]);
1548 break;
1550 case PROTOBUF_C_TYPE_INT64:
1551 case PROTOBUF_C_TYPE_UINT64: {
1552 const uint64_t *arr = (const uint64_t *) array;
1553 for (i = 0; i < count; i++)
1554 rv += uint64_size(arr[i]);
1555 break;
1557 case PROTOBUF_C_TYPE_BOOL:
1558 return count;
1559 default:
1560 PROTOBUF_C__ASSERT_NOT_REACHED();
1562 return rv;
1566 * Pack an array of same field type to a virtual buffer.
1568 * \param field
1569 * Field descriptor.
1570 * \param count
1571 * Number of elements of this type.
1572 * \param array
1573 * The elements to get the size of.
1574 * \param[out] buffer
1575 * Virtual buffer to append data to.
1576 * \return
1577 * Number of bytes packed.
1579 static size_t
1580 pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
1581 unsigned count, const void *array,
1582 ProtobufCBuffer *buffer)
1584 uint8_t scratch[16];
1585 size_t rv = 0;
1586 unsigned i;
1588 switch (field->type) {
1589 case PROTOBUF_C_TYPE_SFIXED32:
1590 case PROTOBUF_C_TYPE_FIXED32:
1591 case PROTOBUF_C_TYPE_FLOAT:
1592 #if !defined(WORDS_BIGENDIAN)
1593 rv = count * 4;
1594 goto no_packing_needed;
1595 #else
1596 for (i = 0; i < count; i++) {
1597 unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
1598 buffer->append(buffer, len, scratch);
1599 rv += len;
1601 break;
1602 #endif
1603 case PROTOBUF_C_TYPE_SFIXED64:
1604 case PROTOBUF_C_TYPE_FIXED64:
1605 case PROTOBUF_C_TYPE_DOUBLE:
1606 #if !defined(WORDS_BIGENDIAN)
1607 rv = count * 8;
1608 goto no_packing_needed;
1609 #else
1610 for (i = 0; i < count; i++) {
1611 unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
1612 buffer->append(buffer, len, scratch);
1613 rv += len;
1615 break;
1616 #endif
1617 case PROTOBUF_C_TYPE_INT32:
1618 for (i = 0; i < count; i++) {
1619 unsigned len = int32_pack(((int32_t *) array)[i], scratch);
1620 buffer->append(buffer, len, scratch);
1621 rv += len;
1623 break;
1624 case PROTOBUF_C_TYPE_SINT32:
1625 for (i = 0; i < count; i++) {
1626 unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
1627 buffer->append(buffer, len, scratch);
1628 rv += len;
1630 break;
1631 case PROTOBUF_C_TYPE_ENUM:
1632 case PROTOBUF_C_TYPE_UINT32:
1633 for (i = 0; i < count; i++) {
1634 unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
1635 buffer->append(buffer, len, scratch);
1636 rv += len;
1638 break;
1639 case PROTOBUF_C_TYPE_SINT64:
1640 for (i = 0; i < count; i++) {
1641 unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
1642 buffer->append(buffer, len, scratch);
1643 rv += len;
1645 break;
1646 case PROTOBUF_C_TYPE_INT64:
1647 case PROTOBUF_C_TYPE_UINT64:
1648 for (i = 0; i < count; i++) {
1649 unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
1650 buffer->append(buffer, len, scratch);
1651 rv += len;
1653 break;
1654 case PROTOBUF_C_TYPE_BOOL:
1655 for (i = 0; i < count; i++) {
1656 unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
1657 buffer->append(buffer, len, scratch);
1658 rv += len;
1660 return count;
1661 default:
1662 PROTOBUF_C__ASSERT_NOT_REACHED();
1664 return rv;
1666 #if !defined(WORDS_BIGENDIAN)
1667 no_packing_needed:
1668 buffer->append(buffer, rv, array);
1669 return rv;
1670 #endif
1673 static size_t
1674 repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1675 unsigned count, const void *member,
1676 ProtobufCBuffer *buffer)
1678 char *array = *(char * const *) member;
1680 if (count == 0)
1681 return 0;
1682 if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1683 uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1684 size_t rv = tag_pack(field->id, scratch);
1685 size_t payload_len = get_packed_payload_length(field, count, array);
1686 size_t tmp;
1688 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1689 rv += uint32_pack(payload_len, scratch + rv);
1690 buffer->append(buffer, rv, scratch);
1691 tmp = pack_buffer_packed_payload(field, count, array, buffer);
1692 assert(tmp == payload_len);
1693 return rv + payload_len;
1694 } else {
1695 size_t siz;
1696 unsigned i;
1697 /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1698 unsigned rv = 0;
1700 siz = sizeof_elt_in_repeated_array(field->type);
1701 for (i = 0; i < count; i++) {
1702 rv += required_field_pack_to_buffer(field, array, buffer);
1703 array = ((char*)array) + siz;
1705 return rv;
1709 static size_t
1710 unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
1711 ProtobufCBuffer *buffer)
1713 uint8_t header[MAX_UINT64_ENCODED_SIZE];
1714 size_t rv = tag_pack(field->tag, header);
1716 header[0] |= field->wire_type;
1717 buffer->append(buffer, rv, header);
1718 buffer->append(buffer, field->len, field->data);
1719 return rv + field->len;
1722 /**@}*/
1724 size_t
1725 protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
1726 ProtobufCBuffer *buffer)
1728 unsigned i;
1729 size_t rv = 0;
1731 ASSERT_IS_MESSAGE(message);
1732 for (i = 0; i < message->descriptor->n_fields; i++) {
1733 const ProtobufCFieldDescriptor *field =
1734 message->descriptor->fields + i;
1735 const void *member =
1736 ((const char *) message) + field->offset;
1737 const void *qmember =
1738 ((const char *) message) + field->quantifier_offset;
1740 if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1741 rv += required_field_pack_to_buffer(field, member, buffer);
1742 } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1743 rv += optional_field_pack_to_buffer(
1744 field,
1745 qmember,
1746 member,
1747 buffer
1749 } else {
1750 rv += repeated_field_pack_to_buffer(
1751 field,
1752 *(const size_t *) qmember,
1753 member,
1754 buffer
1758 for (i = 0; i < message->n_unknown_fields; i++)
1759 rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
1761 return rv;
1765 * \defgroup unpack unpacking implementation
1767 * Routines mainly used by the unpacking functions.
1769 * \ingroup internal
1770 * @{
1773 static inline int
1774 int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
1776 unsigned n;
1777 unsigned start;
1779 if (n_ranges == 0)
1780 return -1;
1781 start = 0;
1782 n = n_ranges;
1783 while (n > 1) {
1784 unsigned mid = start + n / 2;
1786 if (value < ranges[mid].start_value) {
1787 n = mid - start;
1788 } else if (value >= ranges[mid].start_value +
1789 (int) (ranges[mid + 1].orig_index -
1790 ranges[mid].orig_index))
1792 unsigned new_start = mid + 1;
1793 n = start + n - new_start;
1794 start = new_start;
1795 } else
1796 return (value - ranges[mid].start_value) +
1797 ranges[mid].orig_index;
1799 if (n > 0) {
1800 unsigned start_orig_index = ranges[start].orig_index;
1801 unsigned range_size =
1802 ranges[start + 1].orig_index - start_orig_index;
1804 if (ranges[start].start_value <= value &&
1805 value < (int) (ranges[start].start_value + range_size))
1807 return (value - ranges[start].start_value) +
1808 start_orig_index;
1811 return -1;
1814 static size_t
1815 parse_tag_and_wiretype(size_t len,
1816 const uint8_t *data,
1817 uint32_t *tag_out,
1818 ProtobufCWireType *wiretype_out)
1820 unsigned max_rv = len > 5 ? 5 : len;
1821 uint32_t tag = (data[0] & 0x7f) >> 3;
1822 unsigned shift = 4;
1823 unsigned rv;
1825 *wiretype_out = data[0] & 7;
1826 if ((data[0] & 0x80) == 0) {
1827 *tag_out = tag;
1828 return 1;
1830 for (rv = 1; rv < max_rv; rv++) {
1831 if (data[rv] & 0x80) {
1832 tag |= (data[rv] & 0x7f) << shift;
1833 shift += 7;
1834 } else {
1835 tag |= data[rv] << shift;
1836 *tag_out = tag;
1837 return rv + 1;
1840 return 0; /* error: bad header */
1843 /* sizeof(ScannedMember) must be <= (1<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
1844 #define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
1845 typedef struct _ScannedMember ScannedMember;
1846 /** Field as it's being read. */
1847 struct _ScannedMember {
1848 uint32_t tag; /**< Field tag. */
1849 uint8_t wire_type; /**< Field type. */
1850 uint8_t length_prefix_len; /**< Prefix length. */
1851 const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
1852 size_t len; /**< Field length. */
1853 const uint8_t *data; /**< Pointer to field data. */
1856 static inline uint32_t
1857 scan_length_prefixed_data(size_t len, const uint8_t *data,
1858 size_t *prefix_len_out)
1860 unsigned hdr_max = len < 5 ? len : 5;
1861 unsigned hdr_len;
1862 uint32_t val = 0;
1863 unsigned i;
1864 unsigned shift = 0;
1866 for (i = 0; i < hdr_max; i++) {
1867 val |= (data[i] & 0x7f) << shift;
1868 shift += 7;
1869 if ((data[i] & 0x80) == 0)
1870 break;
1872 if (i == hdr_max) {
1873 PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
1874 return 0;
1876 hdr_len = i + 1;
1877 *prefix_len_out = hdr_len;
1878 if (hdr_len + val > len) {
1879 PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val);
1880 return 0;
1882 return hdr_len + val;
1885 static size_t
1886 max_b128_numbers(size_t len, const uint8_t *data)
1888 size_t rv = 0;
1889 while (len--)
1890 if ((*data++ & 0x80) == 0)
1891 ++rv;
1892 return rv;
1895 /**@}*/
1898 * Merge earlier message into a latter message.
1900 * For numeric types and strings, if the same value appears multiple
1901 * times, the parser accepts the last value it sees. For embedded
1902 * message fields, the parser merges multiple instances of the same
1903 * field. That is, all singular scalar fields in the latter instance
1904 * replace those in the former, singular embedded messages are merged,
1905 * and repeated fields are concatenated.
1907 * The earlier message should be freed after calling this function, as
1908 * some of its fields may have been reused and changed to their default
1909 * values during the merge.
1911 static protobuf_c_boolean
1912 merge_messages(ProtobufCMessage *earlier_msg,
1913 ProtobufCMessage *latter_msg,
1914 ProtobufCAllocator *allocator)
1916 unsigned i;
1917 const ProtobufCFieldDescriptor *fields =
1918 earlier_msg->descriptor->fields;
1919 for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
1920 if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
1921 size_t *n_earlier =
1922 STRUCT_MEMBER_PTR(size_t, earlier_msg,
1923 fields[i].quantifier_offset);
1924 uint8_t **p_earlier =
1925 STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
1926 fields[i].offset);
1927 size_t *n_latter =
1928 STRUCT_MEMBER_PTR(size_t, latter_msg,
1929 fields[i].quantifier_offset);
1930 uint8_t **p_latter =
1931 STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
1932 fields[i].offset);
1934 if (*n_earlier > 0) {
1935 if (*n_latter > 0) {
1936 /* Concatenate the repeated field */
1937 size_t el_size =
1938 sizeof_elt_in_repeated_array(fields[i].type);
1939 uint8_t *new_field;
1941 new_field = do_alloc(allocator,
1942 (*n_earlier + *n_latter) * el_size);
1943 if (!new_field)
1944 return FALSE;
1946 memcpy(new_field, *p_earlier,
1947 *n_earlier * el_size);
1948 memcpy(new_field +
1949 *n_earlier * el_size,
1950 *p_latter,
1951 *n_latter * el_size);
1953 do_free(allocator, *p_latter);
1954 do_free(allocator, *p_earlier);
1955 *p_latter = new_field;
1956 *n_latter = *n_earlier + *n_latter;
1957 } else {
1958 /* Zero copy the repeated field from the earlier message */
1959 *n_latter = *n_earlier;
1960 *p_latter = *p_earlier;
1962 /* Make sure the field does not get double freed */
1963 *n_earlier = 0;
1964 *p_earlier = 0;
1966 } else if (fields[i].type == PROTOBUF_C_TYPE_MESSAGE) {
1967 ProtobufCMessage **em =
1968 STRUCT_MEMBER_PTR(ProtobufCMessage *,
1969 earlier_msg,
1970 fields[i].offset);
1971 ProtobufCMessage **lm =
1972 STRUCT_MEMBER_PTR(ProtobufCMessage *,
1973 latter_msg,
1974 fields[i].offset);
1975 if (*em != NULL) {
1976 if (*lm != NULL) {
1977 if (!merge_messages
1978 (*em, *lm, allocator))
1979 return FALSE;
1980 } else {
1981 /* Zero copy the optional message */
1982 assert(fields[i].label ==
1983 PROTOBUF_C_LABEL_OPTIONAL);
1984 *lm = *em;
1985 *em = NULL;
1988 } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) {
1989 size_t el_size = 0;
1990 protobuf_c_boolean need_to_merge = FALSE;
1991 void *earlier_elem =
1992 STRUCT_MEMBER_P(earlier_msg, fields[i].offset);
1993 void *latter_elem =
1994 STRUCT_MEMBER_P(latter_msg, fields[i].offset);
1995 const void *def_val = fields[i].default_value;
1997 switch (fields[i].type) {
1998 case PROTOBUF_C_TYPE_BYTES: {
1999 uint8_t *e_data =
2000 ((ProtobufCBinaryData *) earlier_elem)->data;
2001 uint8_t *l_data =
2002 ((ProtobufCBinaryData *) latter_elem)->data;
2003 const ProtobufCBinaryData *d_bd =
2004 (ProtobufCBinaryData *) def_val;
2006 el_size = sizeof(ProtobufCBinaryData);
2007 need_to_merge =
2008 (e_data != NULL &&
2009 (d_bd != NULL &&
2010 e_data != d_bd->data)) &&
2011 (l_data == NULL ||
2012 (d_bd != NULL &&
2013 l_data == d_bd->data));
2014 break;
2016 case PROTOBUF_C_TYPE_STRING: {
2017 char *e_str = *(char **) earlier_elem;
2018 char *l_str = *(char **) latter_elem;
2019 const char *d_str = def_val;
2021 el_size = sizeof(char *);
2022 need_to_merge = e_str != d_str && l_str == d_str;
2023 break;
2025 default: {
2026 el_size = sizeof_elt_in_repeated_array(fields[i].type);
2028 need_to_merge =
2029 STRUCT_MEMBER(protobuf_c_boolean,
2030 earlier_msg,
2031 fields[i].quantifier_offset) &&
2032 !STRUCT_MEMBER(protobuf_c_boolean,
2033 latter_msg,
2034 fields[i].quantifier_offset);
2035 break;
2039 if (need_to_merge) {
2040 memcpy(latter_elem, earlier_elem, el_size);
2042 * Reset the element from the old message to 0
2043 * to make sure earlier message deallocation
2044 * doesn't corrupt zero-copied data in the new
2045 * message, earlier message will be freed after
2046 * this function is called anyway
2048 memset(earlier_elem, 0, el_size);
2050 if (fields[i].quantifier_offset != 0) {
2051 /* Set the has field, if applicable */
2052 STRUCT_MEMBER(protobuf_c_boolean,
2053 latter_msg,
2054 fields[i].
2055 quantifier_offset) = TRUE;
2056 STRUCT_MEMBER(protobuf_c_boolean,
2057 earlier_msg,
2058 fields[i].
2059 quantifier_offset) = FALSE;
2064 return TRUE;
2068 * Count packed elements.
2070 * Given a raw slab of packed-repeated values, determine the number of
2071 * elements. This function detects certain kinds of errors but not
2072 * others; the remaining error checking is done by
2073 * parse_packed_repeated_member().
2075 static protobuf_c_boolean
2076 count_packed_elements(ProtobufCType type,
2077 size_t len, const uint8_t *data, size_t *count_out)
2079 switch (type) {
2080 case PROTOBUF_C_TYPE_SFIXED32:
2081 case PROTOBUF_C_TYPE_FIXED32:
2082 case PROTOBUF_C_TYPE_FLOAT:
2083 if (len % 4 != 0) {
2084 PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
2085 return FALSE;
2087 *count_out = len / 4;
2088 return TRUE;
2089 case PROTOBUF_C_TYPE_SFIXED64:
2090 case PROTOBUF_C_TYPE_FIXED64:
2091 case PROTOBUF_C_TYPE_DOUBLE:
2092 if (len % 8 != 0) {
2093 PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
2094 return FALSE;
2096 *count_out = len / 8;
2097 return TRUE;
2098 case PROTOBUF_C_TYPE_INT32:
2099 case PROTOBUF_C_TYPE_SINT32:
2100 case PROTOBUF_C_TYPE_ENUM:
2101 case PROTOBUF_C_TYPE_UINT32:
2102 case PROTOBUF_C_TYPE_INT64:
2103 case PROTOBUF_C_TYPE_SINT64:
2104 case PROTOBUF_C_TYPE_UINT64:
2105 *count_out = max_b128_numbers(len, data);
2106 return TRUE;
2107 case PROTOBUF_C_TYPE_BOOL:
2108 *count_out = len;
2109 return TRUE;
2110 case PROTOBUF_C_TYPE_STRING:
2111 case PROTOBUF_C_TYPE_BYTES:
2112 case PROTOBUF_C_TYPE_MESSAGE:
2113 default:
2114 PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
2115 return FALSE;
2119 static inline uint32_t
2120 parse_uint32(unsigned len, const uint8_t *data)
2122 uint32_t rv = data[0] & 0x7f;
2123 if (len > 1) {
2124 rv |= ((uint32_t) (data[1] & 0x7f) << 7);
2125 if (len > 2) {
2126 rv |= ((uint32_t) (data[2] & 0x7f) << 14);
2127 if (len > 3) {
2128 rv |= ((uint32_t) (data[3] & 0x7f) << 21);
2129 if (len > 4)
2130 rv |= ((uint32_t) (data[4]) << 28);
2134 return rv;
2137 static inline uint32_t
2138 parse_int32(unsigned len, const uint8_t *data)
2140 return parse_uint32(len, data);
2143 static inline int32_t
2144 unzigzag32(uint32_t v)
2146 if (v & 1)
2147 return -(v >> 1) - 1;
2148 else
2149 return v >> 1;
2152 static inline uint32_t
2153 parse_fixed_uint32(const uint8_t *data)
2155 #if !defined(WORDS_BIGENDIAN)
2156 uint32_t t;
2157 memcpy(&t, data, 4);
2158 return t;
2159 #else
2160 return data[0] |
2161 ((uint32_t) (data[1]) << 8) |
2162 ((uint32_t) (data[2]) << 16) |
2163 ((uint32_t) (data[3]) << 24);
2164 #endif
2167 static uint64_t
2168 parse_uint64(unsigned len, const uint8_t *data)
2170 unsigned shift, i;
2171 uint64_t rv;
2173 if (len < 5)
2174 return parse_uint32(len, data);
2175 rv = ((uint64_t) (data[0] & 0x7f)) |
2176 ((uint64_t) (data[1] & 0x7f) << 7) |
2177 ((uint64_t) (data[2] & 0x7f) << 14) |
2178 ((uint64_t) (data[3] & 0x7f) << 21);
2179 shift = 28;
2180 for (i = 4; i < len; i++) {
2181 rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
2182 shift += 7;
2184 return rv;
2187 static inline int64_t
2188 unzigzag64(uint64_t v)
2190 if (v & 1)
2191 return -(v >> 1) - 1;
2192 else
2193 return v >> 1;
2196 static inline uint64_t
2197 parse_fixed_uint64(const uint8_t *data)
2199 #if !defined(WORDS_BIGENDIAN)
2200 uint64_t t;
2201 memcpy(&t, data, 8);
2202 return t;
2203 #else
2204 return (uint64_t) parse_fixed_uint32(data) |
2205 (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
2206 #endif
2209 static protobuf_c_boolean
2210 parse_boolean(unsigned len, const uint8_t *data)
2212 unsigned i;
2213 for (i = 0; i < len; i++)
2214 if (data[i] & 0x7f)
2215 return TRUE;
2216 return FALSE;
2219 static protobuf_c_boolean
2220 parse_required_member(ScannedMember *scanned_member,
2221 void *member,
2222 ProtobufCAllocator *allocator,
2223 protobuf_c_boolean maybe_clear)
2225 unsigned len = scanned_member->len;
2226 const uint8_t *data = scanned_member->data;
2227 ProtobufCWireType wire_type = scanned_member->wire_type;
2229 switch (scanned_member->field->type) {
2230 case PROTOBUF_C_TYPE_INT32:
2231 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2232 return FALSE;
2233 *(uint32_t *) member = parse_int32(len, data);
2234 return TRUE;
2235 case PROTOBUF_C_TYPE_UINT32:
2236 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2237 return FALSE;
2238 *(uint32_t *) member = parse_uint32(len, data);
2239 return TRUE;
2240 case PROTOBUF_C_TYPE_SINT32:
2241 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2242 return FALSE;
2243 *(int32_t *) member = unzigzag32(parse_uint32(len, data));
2244 return TRUE;
2245 case PROTOBUF_C_TYPE_SFIXED32:
2246 case PROTOBUF_C_TYPE_FIXED32:
2247 case PROTOBUF_C_TYPE_FLOAT:
2248 if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
2249 return FALSE;
2250 *(uint32_t *) member = parse_fixed_uint32(data);
2251 return TRUE;
2252 case PROTOBUF_C_TYPE_INT64:
2253 case PROTOBUF_C_TYPE_UINT64:
2254 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2255 return FALSE;
2256 *(uint64_t *) member = parse_uint64(len, data);
2257 return TRUE;
2258 case PROTOBUF_C_TYPE_SINT64:
2259 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2260 return FALSE;
2261 *(int64_t *) member = unzigzag64(parse_uint64(len, data));
2262 return TRUE;
2263 case PROTOBUF_C_TYPE_SFIXED64:
2264 case PROTOBUF_C_TYPE_FIXED64:
2265 case PROTOBUF_C_TYPE_DOUBLE:
2266 if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
2267 return FALSE;
2268 *(uint64_t *) member = parse_fixed_uint64(data);
2269 return TRUE;
2270 case PROTOBUF_C_TYPE_BOOL:
2271 *(protobuf_c_boolean *) member = parse_boolean(len, data);
2272 return TRUE;
2273 case PROTOBUF_C_TYPE_ENUM:
2274 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2275 return FALSE;
2276 *(uint32_t *) member = parse_uint32(len, data);
2277 return TRUE;
2278 case PROTOBUF_C_TYPE_STRING: {
2279 char **pstr = member;
2280 unsigned pref_len = scanned_member->length_prefix_len;
2282 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2283 return FALSE;
2285 if (maybe_clear && *pstr != NULL) {
2286 const char *def = scanned_member->field->default_value;
2287 if (*pstr != NULL && *pstr != def)
2288 do_free(allocator, *pstr);
2290 *pstr = do_alloc(allocator, len - pref_len + 1);
2291 if (*pstr == NULL)
2292 return FALSE;
2293 memcpy(*pstr, data + pref_len, len - pref_len);
2294 (*pstr)[len - pref_len] = 0;
2295 return TRUE;
2297 case PROTOBUF_C_TYPE_BYTES: {
2298 ProtobufCBinaryData *bd = member;
2299 const ProtobufCBinaryData *def_bd;
2300 unsigned pref_len = scanned_member->length_prefix_len;
2302 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2303 return FALSE;
2305 def_bd = scanned_member->field->default_value;
2306 if (maybe_clear &&
2307 bd->data != NULL &&
2308 (def_bd == NULL || bd->data != def_bd->data))
2310 do_free(allocator, bd->data);
2312 if (len - pref_len > 0) {
2313 bd->data = do_alloc(allocator, len - pref_len);
2314 if (bd->data == NULL)
2315 return FALSE;
2316 memcpy(bd->data, data + pref_len, len - pref_len);
2317 } else {
2318 bd->data = NULL;
2320 bd->len = len - pref_len;
2321 return TRUE;
2323 case PROTOBUF_C_TYPE_MESSAGE: {
2324 ProtobufCMessage **pmessage = member;
2325 ProtobufCMessage *subm;
2326 const ProtobufCMessage *def_mess;
2327 protobuf_c_boolean merge_successful = TRUE;
2328 unsigned pref_len = scanned_member->length_prefix_len;
2330 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2331 return FALSE;
2333 def_mess = scanned_member->field->default_value;
2334 subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
2335 allocator,
2336 len - pref_len,
2337 data + pref_len);
2339 if (maybe_clear &&
2340 *pmessage != NULL &&
2341 *pmessage != def_mess)
2343 if (subm != NULL)
2344 merge_successful = merge_messages(*pmessage, subm, allocator);
2345 /* Delete the previous message */
2346 protobuf_c_message_free_unpacked(*pmessage, allocator);
2348 *pmessage = subm;
2349 if (subm == NULL || !merge_successful)
2350 return FALSE;
2351 return TRUE;
2354 return FALSE;
2357 static protobuf_c_boolean
2358 parse_optional_member(ScannedMember *scanned_member,
2359 void *member,
2360 ProtobufCMessage *message,
2361 ProtobufCAllocator *allocator)
2363 if (!parse_required_member(scanned_member, member, allocator, TRUE))
2364 return FALSE;
2365 if (scanned_member->field->quantifier_offset != 0)
2366 STRUCT_MEMBER(protobuf_c_boolean,
2367 message,
2368 scanned_member->field->quantifier_offset) = TRUE;
2369 return TRUE;
2372 static protobuf_c_boolean
2373 parse_repeated_member(ScannedMember *scanned_member,
2374 void *member,
2375 ProtobufCMessage *message,
2376 ProtobufCAllocator *allocator)
2378 const ProtobufCFieldDescriptor *field = scanned_member->field;
2379 size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2380 size_t siz = sizeof_elt_in_repeated_array(field->type);
2381 char *array = *(char **) member;
2383 if (!parse_required_member(scanned_member, array + siz * (*p_n),
2384 allocator, FALSE))
2386 return FALSE;
2388 *p_n += 1;
2389 return TRUE;
2392 static unsigned
2393 scan_varint(unsigned len, const uint8_t *data)
2395 unsigned i;
2396 if (len > 10)
2397 len = 10;
2398 for (i = 0; i < len; i++)
2399 if ((data[i] & 0x80) == 0)
2400 break;
2401 if (i == len)
2402 return 0;
2403 return i + 1;
2406 static protobuf_c_boolean
2407 parse_packed_repeated_member(ScannedMember *scanned_member,
2408 void *member,
2409 ProtobufCMessage *message)
2411 const ProtobufCFieldDescriptor *field = scanned_member->field;
2412 size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2413 size_t siz = sizeof_elt_in_repeated_array(field->type);
2414 void *array = *(char **) member + siz * (*p_n);
2415 const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
2416 size_t rem = scanned_member->len - scanned_member->length_prefix_len;
2417 size_t count = 0;
2418 unsigned i;
2420 switch (field->type) {
2421 case PROTOBUF_C_TYPE_SFIXED32:
2422 case PROTOBUF_C_TYPE_FIXED32:
2423 case PROTOBUF_C_TYPE_FLOAT:
2424 count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
2425 #if !defined(WORDS_BIGENDIAN)
2426 goto no_unpacking_needed;
2427 #else
2428 for (i = 0; i < count; i++) {
2429 ((uint32_t *) array)[i] = parse_fixed_uint32(at);
2430 at += 4;
2432 break;
2433 #endif
2434 case PROTOBUF_C_TYPE_SFIXED64:
2435 case PROTOBUF_C_TYPE_FIXED64:
2436 case PROTOBUF_C_TYPE_DOUBLE:
2437 count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
2438 #if !defined(WORDS_BIGENDIAN)
2439 goto no_unpacking_needed;
2440 #else
2441 for (i = 0; i < count; i++) {
2442 ((uint64_t *) array)[i] = parse_fixed_uint64(at);
2443 at += 8;
2445 break;
2446 #endif
2447 case PROTOBUF_C_TYPE_INT32:
2448 while (rem > 0) {
2449 unsigned s = scan_varint(rem, at);
2450 if (s == 0) {
2451 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
2452 return FALSE;
2454 ((int32_t *) array)[count++] = parse_int32(s, at);
2455 at += s;
2456 rem -= s;
2458 break;
2459 case PROTOBUF_C_TYPE_SINT32:
2460 while (rem > 0) {
2461 unsigned s = scan_varint(rem, at);
2462 if (s == 0) {
2463 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
2464 return FALSE;
2466 ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
2467 at += s;
2468 rem -= s;
2470 break;
2471 case PROTOBUF_C_TYPE_ENUM:
2472 case PROTOBUF_C_TYPE_UINT32:
2473 while (rem > 0) {
2474 unsigned s = scan_varint(rem, at);
2475 if (s == 0) {
2476 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
2477 return FALSE;
2479 ((uint32_t *) array)[count++] = parse_uint32(s, at);
2480 at += s;
2481 rem -= s;
2483 break;
2485 case PROTOBUF_C_TYPE_SINT64:
2486 while (rem > 0) {
2487 unsigned s = scan_varint(rem, at);
2488 if (s == 0) {
2489 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
2490 return FALSE;
2492 ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
2493 at += s;
2494 rem -= s;
2496 break;
2497 case PROTOBUF_C_TYPE_INT64:
2498 case PROTOBUF_C_TYPE_UINT64:
2499 while (rem > 0) {
2500 unsigned s = scan_varint(rem, at);
2501 if (s == 0) {
2502 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
2503 return FALSE;
2505 ((int64_t *) array)[count++] = parse_uint64(s, at);
2506 at += s;
2507 rem -= s;
2509 break;
2510 case PROTOBUF_C_TYPE_BOOL:
2511 count = rem;
2512 for (i = 0; i < count; i++) {
2513 if (at[i] > 1) {
2514 PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
2515 return FALSE;
2517 ((protobuf_c_boolean *) array)[i] = at[i];
2519 break;
2520 default:
2521 PROTOBUF_C__ASSERT_NOT_REACHED();
2523 *p_n += count;
2524 return TRUE;
2526 #if !defined(WORDS_BIGENDIAN)
2527 no_unpacking_needed:
2528 memcpy(array, at, count * siz);
2529 *p_n += count;
2530 return TRUE;
2531 #endif
2534 static protobuf_c_boolean
2535 is_packable_type(ProtobufCType type)
2537 return
2538 type != PROTOBUF_C_TYPE_STRING &&
2539 type != PROTOBUF_C_TYPE_BYTES &&
2540 type != PROTOBUF_C_TYPE_MESSAGE;
2543 static protobuf_c_boolean
2544 parse_member(ScannedMember *scanned_member,
2545 ProtobufCMessage *message,
2546 ProtobufCAllocator *allocator)
2548 const ProtobufCFieldDescriptor *field = scanned_member->field;
2549 void *member;
2551 if (field == NULL) {
2552 ProtobufCMessageUnknownField *ufield =
2553 message->unknown_fields +
2554 (message->n_unknown_fields++);
2555 ufield->tag = scanned_member->tag;
2556 ufield->wire_type = scanned_member->wire_type;
2557 ufield->len = scanned_member->len;
2558 ufield->data = do_alloc(allocator, scanned_member->len);
2559 if (ufield->data == NULL)
2560 return FALSE;
2561 memcpy(ufield->data, scanned_member->data, ufield->len);
2562 return TRUE;
2564 member = (char *) message + field->offset;
2565 switch (field->label) {
2566 case PROTOBUF_C_LABEL_REQUIRED:
2567 return parse_required_member(scanned_member, member,
2568 allocator, TRUE);
2569 case PROTOBUF_C_LABEL_OPTIONAL:
2570 return parse_optional_member(scanned_member, member,
2571 message, allocator);
2572 case PROTOBUF_C_LABEL_REPEATED:
2573 if (scanned_member->wire_type ==
2574 PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
2575 (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
2576 is_packable_type(field->type)))
2578 return parse_packed_repeated_member(scanned_member,
2579 member, message);
2580 } else {
2581 return parse_repeated_member(scanned_member,
2582 member, message,
2583 allocator);
2586 PROTOBUF_C__ASSERT_NOT_REACHED();
2587 return 0;
2591 * Initialise messages generated by old code.
2593 * This function is used if desc->message_init == NULL (which occurs
2594 * for old code, and which would be useful to support allocating
2595 * descriptors dynamically).
2597 static void
2598 message_init_generic(const ProtobufCMessageDescriptor *desc,
2599 ProtobufCMessage *message)
2601 unsigned i;
2603 memset(message, 0, desc->sizeof_message);
2604 message->descriptor = desc;
2605 for (i = 0; i < desc->n_fields; i++) {
2606 if (desc->fields[i].default_value != NULL &&
2607 desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
2609 void *field =
2610 STRUCT_MEMBER_P(message, desc->fields[i].offset);
2611 const void *dv = desc->fields[i].default_value;
2613 switch (desc->fields[i].type) {
2614 case PROTOBUF_C_TYPE_INT32:
2615 case PROTOBUF_C_TYPE_SINT32:
2616 case PROTOBUF_C_TYPE_SFIXED32:
2617 case PROTOBUF_C_TYPE_UINT32:
2618 case PROTOBUF_C_TYPE_FIXED32:
2619 case PROTOBUF_C_TYPE_FLOAT:
2620 case PROTOBUF_C_TYPE_ENUM:
2621 memcpy(field, dv, 4);
2622 break;
2623 case PROTOBUF_C_TYPE_INT64:
2624 case PROTOBUF_C_TYPE_SINT64:
2625 case PROTOBUF_C_TYPE_SFIXED64:
2626 case PROTOBUF_C_TYPE_UINT64:
2627 case PROTOBUF_C_TYPE_FIXED64:
2628 case PROTOBUF_C_TYPE_DOUBLE:
2629 memcpy(field, dv, 8);
2630 break;
2631 case PROTOBUF_C_TYPE_BOOL:
2632 memcpy(field, dv, sizeof(protobuf_c_boolean));
2633 break;
2634 case PROTOBUF_C_TYPE_BYTES:
2635 memcpy(field, dv, sizeof(ProtobufCBinaryData));
2636 break;
2638 case PROTOBUF_C_TYPE_STRING:
2639 case PROTOBUF_C_TYPE_MESSAGE:
2641 * The next line essentially implements a cast
2642 * from const, which is totally unavoidable.
2644 *(const void **) field = dv;
2645 break;
2651 /**@}*/
2654 * ScannedMember slabs (an unpacking implementation detail). Before doing real
2655 * unpacking, we first scan through the elements to see how many there are (for
2656 * repeated fields), and which field to use (for non-repeated fields given
2657 * twice).
2659 * In order to avoid allocations for small messages, we keep a stack-allocated
2660 * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
2661 * fill that up, we allocate each slab twice as large as the previous one.
2663 #define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
2666 * The number of slabs, including the stack-allocated ones; choose the number so
2667 * that we would overflow if we needed a slab larger than provided.
2669 #define MAX_SCANNED_MEMBER_SLAB \
2670 (sizeof(unsigned int)*8 - 1 \
2671 - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
2672 - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
2674 #define REQUIRED_FIELD_BITMAP_SET(index) \
2675 (required_fields_bitmap[(index)/8] |= (1<<((index)%8)))
2677 #define REQUIRED_FIELD_BITMAP_IS_SET(index) \
2678 (required_fields_bitmap[(index)/8] & (1<<((index)%8)))
2680 ProtobufCMessage *
2681 protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
2682 ProtobufCAllocator *allocator,
2683 size_t len, const uint8_t *data)
2685 ProtobufCMessage *rv;
2686 size_t rem = len;
2687 const uint8_t *at = data;
2688 const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
2689 ScannedMember first_member_slab[1 <<
2690 FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
2693 * scanned_member_slabs[i] is an array of arrays of ScannedMember.
2694 * The first slab (scanned_member_slabs[0] is just a pointer to
2695 * first_member_slab), above. All subsequent slabs will be allocated
2696 * using the allocator.
2698 ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
2699 unsigned which_slab = 0; /* the slab we are currently populating */
2700 unsigned in_slab_index = 0; /* number of members in the slab */
2701 size_t n_unknown = 0;
2702 unsigned f;
2703 unsigned j;
2704 unsigned i_slab;
2705 unsigned last_field_index = 0;
2706 unsigned required_fields_bitmap_len;
2707 unsigned char required_fields_bitmap_stack[16];
2708 unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
2709 protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
2711 ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
2713 if (allocator == NULL)
2714 allocator = &protobuf_c__allocator;
2716 rv = do_alloc(allocator, desc->sizeof_message);
2717 if (!rv)
2718 return (NULL);
2719 scanned_member_slabs[0] = first_member_slab;
2721 required_fields_bitmap_len = (desc->n_fields + 7) / 8;
2722 if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
2723 required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
2724 if (!required_fields_bitmap) {
2725 do_free(allocator, rv);
2726 return (NULL);
2728 required_fields_bitmap_alloced = TRUE;
2730 memset(required_fields_bitmap, 0, required_fields_bitmap_len);
2733 * Generated code always defines "message_init". However, we provide a
2734 * fallback for (1) users of old protobuf-c generated-code that do not
2735 * provide the function, and (2) descriptors constructed from some other
2736 * source (most likely, direct construction from the .proto file).
2738 if (desc->message_init != NULL)
2739 protobuf_c_message_init(desc, rv);
2740 else
2741 message_init_generic(desc, rv);
2743 while (rem > 0) {
2744 uint32_t tag;
2745 ProtobufCWireType wire_type;
2746 size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
2747 const ProtobufCFieldDescriptor *field;
2748 ScannedMember tmp;
2750 memset(&tmp, 0, sizeof(ScannedMember));
2752 if (used == 0) {
2753 PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
2754 (unsigned) (at - data));
2755 goto error_cleanup_during_scan;
2758 * \todo Consider optimizing for field[1].id == tag, if field[1]
2759 * exists!
2761 if (last_field == NULL || last_field->id != tag) {
2762 /* lookup field */
2763 int field_index =
2764 int_range_lookup(desc->n_field_ranges,
2765 desc->field_ranges,
2766 tag);
2767 if (field_index < 0) {
2768 field = NULL;
2769 n_unknown++;
2770 } else {
2771 field = desc->fields + field_index;
2772 last_field = field;
2773 last_field_index = field_index;
2775 } else {
2776 field = last_field;
2779 if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
2780 REQUIRED_FIELD_BITMAP_SET(last_field_index);
2782 at += used;
2783 rem -= used;
2784 tmp.tag = tag;
2785 tmp.wire_type = wire_type;
2786 tmp.field = field;
2787 tmp.data = at;
2788 tmp.length_prefix_len = 0;
2790 switch (wire_type) {
2791 case PROTOBUF_C_WIRE_TYPE_VARINT: {
2792 unsigned max_len = rem < 10 ? rem : 10;
2793 unsigned i;
2795 for (i = 0; i < max_len; i++)
2796 if ((at[i] & 0x80) == 0)
2797 break;
2798 if (i == max_len) {
2799 PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
2800 (unsigned) (at - data));
2801 goto error_cleanup_during_scan;
2803 tmp.len = i + 1;
2804 break;
2806 case PROTOBUF_C_WIRE_TYPE_64BIT:
2807 if (rem < 8) {
2808 PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
2809 (unsigned) (at - data));
2810 goto error_cleanup_during_scan;
2812 tmp.len = 8;
2813 break;
2814 case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
2815 size_t pref_len;
2817 tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
2818 if (tmp.len == 0) {
2819 /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
2820 goto error_cleanup_during_scan;
2822 tmp.length_prefix_len = pref_len;
2823 break;
2825 case PROTOBUF_C_WIRE_TYPE_32BIT:
2826 if (rem < 4) {
2827 PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
2828 (unsigned) (at - data));
2829 goto error_cleanup_during_scan;
2831 tmp.len = 4;
2832 break;
2833 default:
2834 PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
2835 wire_type, (unsigned) (at - data));
2836 goto error_cleanup_during_scan;
2839 if (in_slab_index == (1U <<
2840 (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
2842 size_t size;
2844 in_slab_index = 0;
2845 if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
2846 PROTOBUF_C_UNPACK_ERROR("too many fields");
2847 goto error_cleanup_during_scan;
2849 which_slab++;
2850 size = sizeof(ScannedMember)
2851 << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
2852 scanned_member_slabs[which_slab] = do_alloc(allocator, size);
2853 if (scanned_member_slabs[which_slab] == NULL)
2854 goto error_cleanup_during_scan;
2856 scanned_member_slabs[which_slab][in_slab_index++] = tmp;
2858 if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
2859 size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
2860 field->quantifier_offset);
2861 if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
2862 (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
2863 is_packable_type(field->type)))
2865 size_t count;
2866 if (!count_packed_elements(field->type,
2867 tmp.len -
2868 tmp.length_prefix_len,
2869 tmp.data +
2870 tmp.length_prefix_len,
2871 &count))
2873 PROTOBUF_C_UNPACK_ERROR("counting packed elements");
2874 goto error_cleanup_during_scan;
2876 *n += count;
2877 } else {
2878 *n += 1;
2882 at += tmp.len;
2883 rem -= tmp.len;
2886 /* allocate space for repeated fields, also check that all required fields have been set */
2887 for (f = 0; f < desc->n_fields; f++) {
2888 const ProtobufCFieldDescriptor *field = desc->fields + f;
2889 if (field->label == PROTOBUF_C_LABEL_REPEATED) {
2890 size_t siz =
2891 sizeof_elt_in_repeated_array(field->type);
2892 size_t *n_ptr =
2893 STRUCT_MEMBER_PTR(size_t, rv,
2894 field->quantifier_offset);
2895 if (*n_ptr != 0) {
2896 unsigned n = *n_ptr;
2897 void *a;
2898 *n_ptr = 0;
2899 assert(rv->descriptor != NULL);
2900 #define CLEAR_REMAINING_N_PTRS() \
2901 for(f++;f < desc->n_fields; f++) \
2903 field = desc->fields + f; \
2904 if (field->label == PROTOBUF_C_LABEL_REPEATED) \
2905 STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
2907 a = do_alloc(allocator, siz * n);
2908 if (!a) {
2909 CLEAR_REMAINING_N_PTRS();
2910 goto error_cleanup;
2912 STRUCT_MEMBER(void *, rv, field->offset) = a;
2914 } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
2915 if (field->default_value == NULL &&
2916 !REQUIRED_FIELD_BITMAP_IS_SET(f))
2918 CLEAR_REMAINING_N_PTRS();
2919 PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
2920 desc->name, field->name);
2921 goto error_cleanup;
2925 #undef CLEAR_REMAINING_N_PTRS
2927 /* allocate space for unknown fields */
2928 if (n_unknown) {
2929 rv->unknown_fields = do_alloc(allocator,
2930 n_unknown * sizeof(ProtobufCMessageUnknownField));
2931 if (rv->unknown_fields == NULL)
2932 goto error_cleanup;
2935 /* do real parsing */
2936 for (i_slab = 0; i_slab <= which_slab; i_slab++) {
2937 unsigned max = (i_slab == which_slab) ?
2938 in_slab_index : (1U << (i_slab + 4));
2939 ScannedMember *slab = scanned_member_slabs[i_slab];
2940 unsigned j;
2942 for (j = 0; j < max; j++) {
2943 if (!parse_member(slab + j, rv, allocator)) {
2944 PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
2945 slab->field ? slab->field->name : "*unknown-field*",
2946 desc->name);
2947 goto error_cleanup;
2952 /* cleanup */
2953 for (j = 1; j <= which_slab; j++)
2954 do_free(allocator, scanned_member_slabs[j]);
2955 if (required_fields_bitmap_alloced)
2956 do_free(allocator, required_fields_bitmap);
2957 return rv;
2959 error_cleanup:
2960 protobuf_c_message_free_unpacked(rv, allocator);
2961 for (j = 1; j <= which_slab; j++)
2962 do_free(allocator, scanned_member_slabs[j]);
2963 if (required_fields_bitmap_alloced)
2964 do_free(allocator, required_fields_bitmap);
2965 return NULL;
2967 error_cleanup_during_scan:
2968 do_free(allocator, rv);
2969 for (j = 1; j <= which_slab; j++)
2970 do_free(allocator, scanned_member_slabs[j]);
2971 if (required_fields_bitmap_alloced)
2972 do_free(allocator, required_fields_bitmap);
2973 return NULL;
2976 void
2977 protobuf_c_message_free_unpacked(ProtobufCMessage *message,
2978 ProtobufCAllocator *allocator)
2980 const ProtobufCMessageDescriptor *desc = message->descriptor;
2981 unsigned f;
2983 ASSERT_IS_MESSAGE(message);
2984 if (allocator == NULL)
2985 allocator = &protobuf_c__allocator;
2986 message->descriptor = NULL;
2987 for (f = 0; f < desc->n_fields; f++) {
2988 if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
2989 size_t n = STRUCT_MEMBER(size_t,
2990 message,
2991 desc->fields[f].quantifier_offset);
2992 void *arr = STRUCT_MEMBER(void *,
2993 message,
2994 desc->fields[f].offset);
2996 if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
2997 unsigned i;
2998 for (i = 0; i < n; i++)
2999 do_free(allocator, ((char **) arr)[i]);
3000 } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3001 unsigned i;
3002 for (i = 0; i < n; i++)
3003 do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
3004 } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3005 unsigned i;
3006 for (i = 0; i < n; i++)
3007 protobuf_c_message_free_unpacked(
3008 ((ProtobufCMessage **) arr)[i],
3009 allocator
3012 if (arr != NULL)
3013 do_free(allocator, arr);
3014 } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3015 char *str = STRUCT_MEMBER(char *, message,
3016 desc->fields[f].offset);
3018 if (str && str != desc->fields[f].default_value)
3019 do_free(allocator, str);
3020 } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3021 void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
3022 desc->fields[f].offset).data;
3023 const ProtobufCBinaryData *default_bd;
3025 default_bd = desc->fields[f].default_value;
3026 if (data != NULL &&
3027 (default_bd == NULL ||
3028 default_bd->data != data))
3030 do_free(allocator, data);
3032 } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3033 ProtobufCMessage *sm;
3035 sm = STRUCT_MEMBER(ProtobufCMessage *, message,
3036 desc->fields[f].offset);
3037 if (sm && sm != desc->fields[f].default_value)
3038 protobuf_c_message_free_unpacked(sm, allocator);
3042 for (f = 0; f < message->n_unknown_fields; f++)
3043 do_free(allocator, message->unknown_fields[f].data);
3044 if (message->unknown_fields != NULL)
3045 do_free(allocator, message->unknown_fields);
3047 do_free(allocator, message);
3050 void
3051 protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
3052 void *message)
3054 descriptor->message_init((ProtobufCMessage *) (message));
3057 protobuf_c_boolean
3058 protobuf_c_message_check(const ProtobufCMessage *message)
3060 unsigned i;
3062 if (!message ||
3063 !message->descriptor ||
3064 message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
3066 return FALSE;
3069 for (i = 0; i < message->descriptor->n_fields; i++) {
3070 const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
3071 ProtobufCType type = f->type;
3072 ProtobufCLabel label = f->label;
3073 void *field = STRUCT_MEMBER_P (message, f->offset);
3075 if (label == PROTOBUF_C_LABEL_REPEATED) {
3076 size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
3078 if (*quantity > 0 && *(void **) field == NULL) {
3079 return FALSE;
3082 if (type == PROTOBUF_C_TYPE_MESSAGE) {
3083 ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
3084 unsigned j;
3085 for (j = 0; j < *quantity; j++) {
3086 if (!protobuf_c_message_check(submessage[j]))
3087 return FALSE;
3089 } else if (type == PROTOBUF_C_TYPE_STRING) {
3090 char **string = *(char ***) field;
3091 unsigned j;
3092 for (j = 0; j < *quantity; j++) {
3093 if (!string[j])
3094 return FALSE;
3096 } else if (type == PROTOBUF_C_TYPE_BYTES) {
3097 ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
3098 unsigned j;
3099 for (j = 0; j < *quantity; j++) {
3100 if (bd[j].len > 0 && bd[j].data == NULL)
3101 return FALSE;
3105 } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
3107 if (type == PROTOBUF_C_TYPE_MESSAGE) {
3108 ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
3109 if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
3110 if (!protobuf_c_message_check(submessage))
3111 return FALSE;
3113 } else if (type == PROTOBUF_C_TYPE_STRING) {
3114 char *string = *(char **) field;
3115 if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
3116 return FALSE;
3117 } else if (type == PROTOBUF_C_TYPE_BYTES) {
3118 protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
3119 ProtobufCBinaryData *bd = field;
3120 if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
3121 if (bd->len > 0 && bd->data == NULL)
3122 return FALSE;
3128 return TRUE;
3131 /* === services === */
3133 typedef void (*GenericHandler) (void *service,
3134 const ProtobufCMessage *input,
3135 ProtobufCClosure closure,
3136 void *closure_data);
3137 void
3138 protobuf_c_service_invoke_internal(ProtobufCService *service,
3139 unsigned method_index,
3140 const ProtobufCMessage *input,
3141 ProtobufCClosure closure,
3142 void *closure_data)
3144 GenericHandler *handlers;
3145 GenericHandler handler;
3148 * Verify that method_index is within range. If this fails, you are
3149 * likely invoking a newly added method on an old service. (Although
3150 * other memory corruption bugs can cause this assertion too.)
3152 assert(method_index < service->descriptor->n_methods);
3155 * Get the array of virtual methods (which are enumerated by the
3156 * generated code).
3158 handlers = (GenericHandler *) (service + 1);
3161 * Get our method and invoke it.
3162 * \todo Seems like handler == NULL is a situation that needs handling.
3164 handler = handlers[method_index];
3165 (*handler)(service, input, closure, closure_data);
3168 void
3169 protobuf_c_service_generated_init(ProtobufCService *service,
3170 const ProtobufCServiceDescriptor *descriptor,
3171 ProtobufCServiceDestroy destroy)
3173 ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
3174 service->descriptor = descriptor;
3175 service->destroy = destroy;
3176 service->invoke = protobuf_c_service_invoke_internal;
3177 memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
3180 void protobuf_c_service_destroy(ProtobufCService *service)
3182 service->destroy(service);
3185 /* --- querying the descriptors --- */
3187 const ProtobufCEnumValue *
3188 protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
3189 const char *name)
3191 unsigned start = 0;
3192 unsigned count = desc->n_value_names;
3194 while (count > 1) {
3195 unsigned mid = start + count / 2;
3196 int rv = strcmp(desc->values_by_name[mid].name, name);
3197 if (rv == 0)
3198 return desc->values + desc->values_by_name[mid].index;
3199 else if (rv < 0) {
3200 count = start + count - (mid + 1);
3201 start = mid + 1;
3202 } else
3203 count = mid - start;
3205 if (count == 0)
3206 return NULL;
3207 if (purple_strequal(desc->values_by_name[start].name, name))
3208 return desc->values + desc->values_by_name[start].index;
3209 return NULL;
3212 const ProtobufCEnumValue *
3213 protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
3214 int value)
3216 int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
3217 if (rv < 0)
3218 return NULL;
3219 return desc->values + rv;
3222 const ProtobufCFieldDescriptor *
3223 protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
3224 const char *name)
3226 unsigned start = 0;
3227 unsigned count = desc->n_fields;
3228 const ProtobufCFieldDescriptor *field;
3230 while (count > 1) {
3231 unsigned mid = start + count / 2;
3232 int rv;
3233 field = desc->fields + desc->fields_sorted_by_name[mid];
3234 rv = strcmp(field->name, name);
3235 if (rv == 0)
3236 return field;
3237 else if (rv < 0) {
3238 count = start + count - (mid + 1);
3239 start = mid + 1;
3240 } else
3241 count = mid - start;
3243 if (count == 0)
3244 return NULL;
3245 field = desc->fields + desc->fields_sorted_by_name[start];
3246 if (purple_strequal(field->name, name))
3247 return field;
3248 return NULL;
3251 const ProtobufCFieldDescriptor *
3252 protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
3253 unsigned value)
3255 int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
3256 if (rv < 0)
3257 return NULL;
3258 return desc->fields + rv;
3261 const ProtobufCMethodDescriptor *
3262 protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
3263 const char *name)
3265 unsigned start = 0;
3266 unsigned count = desc->n_methods;
3268 while (count > 1) {
3269 unsigned mid = start + count / 2;
3270 unsigned mid_index = desc->method_indices_by_name[mid];
3271 const char *mid_name = desc->methods[mid_index].name;
3272 int rv = strcmp(mid_name, name);
3274 if (rv == 0)
3275 return desc->methods + desc->method_indices_by_name[mid];
3276 if (rv < 0) {
3277 count = start + count - (mid + 1);
3278 start = mid + 1;
3279 } else {
3280 count = mid - start;
3283 if (count == 0)
3284 return NULL;
3285 if (purple_strequal(desc->methods[desc->method_indices_by_name[start]].name, name))
3286 return desc->methods + desc->method_indices_by_name[start];
3287 return NULL;