1 /* --- protobuf-c.c: public protobuf c runtime implementation --- */
4 * Copyright 2008, Dave Benson.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License
9 * at http://www.apache.org/licenses/LICENSE-2.0 Unless
10 * required by applicable law or agreed to in writing,
11 * software distributed under the License is distributed on
12 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 * KIND, either express or implied. See the License for the
14 * specific language governing permissions and limitations
20 * 64-BIT OPTIMIZATION: certain implementations use 32-bit math even on 64-bit platforms
21 (uint64_size, uint64_pack, parse_uint64)
23 * get_packed_size and pack seem to use type-prefixed names,
24 whereas parse uses type-suffixed names. pick one and stick with it.
25 Decision: go with type-suffixed, since the type (or its instance)
26 is typically the object of the verb.
27 NOTE: perhaps the "parse" methods should be reanemd to "unpack"
28 at the same time. (this only affects internal (static) functions)
30 * use TRUE and FALSE instead of 1 and 0 as appropriate
32 * use size_t consistently
35 #include <stdio.h> /* for occasional printf()s */
36 #include <stdlib.h> /* for abort(), malloc() etc */
37 #include <string.h> /* for strlen(), memcpy(), memmove() */
39 #ifndef PRINT_UNPACK_ERRORS
40 #define PRINT_UNPACK_ERRORS 1
43 #include "protobuf-c.h"
45 #define MAX_UINT64_ENCODED_SIZE 10
47 /* convenience macros */
48 #define TMPALLOC(allocator, size) ((allocator)->tmp_alloc ((allocator)->allocator_data, (size)))
49 #define FREE(allocator, ptr) \
50 do { if ((ptr) != NULL) ((allocator)->free ((allocator)->allocator_data, (ptr))); } while(0)
51 #define UNALIGNED_ALLOC(allocator, size) ALLOC (allocator, size) /* placeholder */
52 #define STRUCT_MEMBER_P(struct_p, struct_offset) \
53 ((void *) ((uint8_t*) (struct_p) + (struct_offset)))
54 #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
55 (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
56 #define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
57 ((member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset)))
62 alloc_failed_warning (unsigned size, const char *filename, unsigned line)
65 "WARNING: out-of-memory allocating a block of size %u (%s:%u)\n",
66 size, filename, line);
69 /* Try to allocate memory, running some special code if it fails. */
70 #define DO_ALLOC(dst, allocator, size, fail_code) \
71 { size_t da__allocation_size = (size); \
72 if (da__allocation_size == 0) \
74 else if ((dst=((allocator)->alloc ((allocator)->allocator_data, \
75 da__allocation_size))) == NULL) \
77 alloc_failed_warning (da__allocation_size, __FILE__, __LINE__); \
81 #define DO_UNALIGNED_ALLOC DO_ALLOC /* placeholder */
85 #define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
86 assert((desc)->magic == PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC)
87 #define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
88 assert((desc)->magic == PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC)
89 #define ASSERT_IS_MESSAGE(message) \
90 ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
91 #define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
92 assert((desc)->magic == PROTOBUF_C_SERVICE_DESCRIPTOR_MAGIC)
94 /* --- allocator --- */
96 static void protobuf_c_out_of_memory_default (void)
98 fprintf (stderr, "Out Of Memory!!!\n");
101 void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
103 static void *system_alloc(void *allocator_data, size_t size)
106 (void) allocator_data;
111 protobuf_c_out_of_memory ();
115 static void system_free (void *allocator_data, void *data)
117 (void) allocator_data;
122 /* Some users may configure the default allocator;
123 providing your own allocator to unpack() is prefered.
124 this allocator is still used for packing nested messages. */
125 ProtobufCAllocator protobuf_c_default_allocator =
134 /* Users should NOT modify this structure,
135 but it's difficult to prevent.
137 please modify protobuf_c_default_allocator instead. */
138 ProtobufCAllocator protobuf_c_system_allocator =
147 /* === buffer-simple === */
149 protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
153 ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
154 size_t new_len = simp->len + len;
155 if (new_len > simp->alloced)
157 size_t new_alloced = simp->alloced * 2;
159 while (new_alloced < new_len)
160 new_alloced += new_alloced;
161 DO_ALLOC (new_data, &protobuf_c_default_allocator, new_alloced, return);
162 memcpy (new_data, simp->data, simp->len);
163 if (simp->must_free_data)
164 FREE (&protobuf_c_default_allocator, simp->data);
166 simp->must_free_data = 1;
167 simp->data = new_data;
168 simp->alloced = new_alloced;
170 memcpy (simp->data + simp->len, data, len);
174 /* === get_packed_size() === */
176 /* Return the number of bytes required to store the
177 tag for the field (which includes 3 bits for
178 the wire-type, and a single bit that denotes the end-of-tag. */
180 get_tag_size (unsigned number)
184 else if (number < (1<<11))
186 else if (number < (1<<18))
188 else if (number < (1<<25))
194 /* Return the number of bytes required to store
195 a variable-length unsigned integer that fits in 32-bit uint
196 in base-128 encoding. */
198 uint32_size (uint32_t v)
202 else if (v < (1<<14))
204 else if (v < (1<<21))
206 else if (v < (1<<28))
211 /* Return the number of bytes required to store
212 a variable-length signed integer that fits in 32-bit int
213 in base-128 encoding. */
215 int32_size (int32_t v)
221 else if (v < (1<<14))
223 else if (v < (1<<21))
225 else if (v < (1<<28))
230 /* return the zigzag-encoded 32-bit unsigned int from a 32-bit signed int */
231 static inline uint32_t
235 return ((uint32_t)(-v)) * 2 - 1;
239 /* Return the number of bytes required to store
240 a variable-length signed integer that fits in 32-bit int,
241 converted to unsigned via the zig-zag algorithm,
242 then packed using base-128 encoding. */
244 sint32_size (int32_t v)
246 return uint32_size(zigzag32(v));
249 /* Return the number of bytes required to store
250 a variable-length unsigned integer that fits in 64-bit uint
251 in base-128 encoding. */
253 uint64_size (uint64_t v)
255 uint32_t upper_v = (v>>32);
257 return uint32_size ((uint32_t)v);
258 else if (upper_v < (1<<3))
260 else if (upper_v < (1<<10))
262 else if (upper_v < (1<<17))
264 else if (upper_v < (1<<24))
266 else if (upper_v < (1U<<31))
272 /* return the zigzag-encoded 64-bit unsigned int from a 64-bit signed int */
273 static inline uint64_t
277 return ((uint64_t)(-v)) * 2 - 1;
282 /* Return the number of bytes required to store
283 a variable-length signed integer that fits in 64-bit int,
284 converted to unsigned via the zig-zag algorithm,
285 then packed using base-128 encoding. */
287 sint64_size (int64_t v)
289 return uint64_size(zigzag64(v));
292 /* Get serialized size of a single field in the message,
293 including the space needed by the identifying tag. */
295 required_field_get_packed_size (const ProtobufCFieldDescriptor *field,
298 size_t rv = get_tag_size (field->id);
301 case PROTOBUF_C_TYPE_SINT32:
302 return rv + sint32_size (*(const int32_t *) member);
303 case PROTOBUF_C_TYPE_INT32:
304 return rv + int32_size (*(const uint32_t *) member);
305 case PROTOBUF_C_TYPE_UINT32:
306 return rv + uint32_size (*(const uint32_t *) member);
307 case PROTOBUF_C_TYPE_SINT64:
308 return rv + sint64_size (*(const int64_t *) member);
309 case PROTOBUF_C_TYPE_INT64:
310 case PROTOBUF_C_TYPE_UINT64:
311 return rv + uint64_size (*(const uint64_t *) member);
312 case PROTOBUF_C_TYPE_SFIXED32:
313 case PROTOBUF_C_TYPE_FIXED32:
315 case PROTOBUF_C_TYPE_SFIXED64:
316 case PROTOBUF_C_TYPE_FIXED64:
318 case PROTOBUF_C_TYPE_BOOL:
320 case PROTOBUF_C_TYPE_FLOAT:
322 case PROTOBUF_C_TYPE_DOUBLE:
324 case PROTOBUF_C_TYPE_ENUM:
325 // TODO: is this correct for negative-valued enums?
326 return rv + uint32_size (*(const uint32_t *) member);
327 case PROTOBUF_C_TYPE_STRING:
329 const char *str = *(char * const *) member;
330 size_t len = str ? strlen (str) : 0;
331 return rv + uint32_size (len) + len;
333 case PROTOBUF_C_TYPE_BYTES:
335 size_t len = ((const ProtobufCBinaryData*) member)->len;
336 return rv + uint32_size (len) + len;
338 //case PROTOBUF_C_TYPE_GROUP:
339 case PROTOBUF_C_TYPE_MESSAGE:
341 const ProtobufCMessage *msg = * (ProtobufCMessage * const *) member;
342 size_t subrv = msg ? protobuf_c_message_get_packed_size (msg) : 0;
343 return rv + uint32_size (subrv) + subrv;
346 PROTOBUF_C_ASSERT_NOT_REACHED ();
350 /* Get serialized size of a single optional field in the message,
351 including the space needed by the identifying tag.
352 Returns 0 if the optional field isn't set. */
354 optional_field_get_packed_size (const ProtobufCFieldDescriptor *field,
355 const protobuf_c_boolean *has,
358 if (field->type == PROTOBUF_C_TYPE_MESSAGE
359 || field->type == PROTOBUF_C_TYPE_STRING)
361 const void *ptr = * (const void * const *) member;
363 || ptr == field->default_value)
371 return required_field_get_packed_size (field, member);
374 /* Get serialized size of a repeated field in the message,
375 which may consist of any number of values (including 0).
376 Includes the space needed by the identifying tags (as needed). */
378 repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field,
385 void *array = * (void * const *) member;
388 header_size = get_tag_size (field->id);
390 header_size *= count;
393 case PROTOBUF_C_TYPE_SINT32:
394 for (i = 0; i < count; i++)
395 rv += sint32_size (((int32_t*)array)[i]);
397 case PROTOBUF_C_TYPE_INT32:
398 for (i = 0; i < count; i++)
399 rv += int32_size (((uint32_t*)array)[i]);
401 case PROTOBUF_C_TYPE_UINT32:
402 case PROTOBUF_C_TYPE_ENUM:
403 for (i = 0; i < count; i++)
404 rv += uint32_size (((uint32_t*)array)[i]);
406 case PROTOBUF_C_TYPE_SINT64:
407 for (i = 0; i < count; i++)
408 rv += sint64_size (((int64_t*)array)[i]);
410 case PROTOBUF_C_TYPE_INT64:
411 case PROTOBUF_C_TYPE_UINT64:
412 for (i = 0; i < count; i++)
413 rv += uint64_size (((uint64_t*)array)[i]);
415 case PROTOBUF_C_TYPE_SFIXED32:
416 case PROTOBUF_C_TYPE_FIXED32:
417 case PROTOBUF_C_TYPE_FLOAT:
420 case PROTOBUF_C_TYPE_SFIXED64:
421 case PROTOBUF_C_TYPE_FIXED64:
422 case PROTOBUF_C_TYPE_DOUBLE:
425 case PROTOBUF_C_TYPE_BOOL:
428 case PROTOBUF_C_TYPE_STRING:
429 for (i = 0; i < count; i++)
431 size_t len = strlen (((char**) array)[i]);
432 rv += uint32_size (len) + len;
436 case PROTOBUF_C_TYPE_BYTES:
437 for (i = 0; i < count; i++)
439 size_t len = ((ProtobufCBinaryData*) array)[i].len;
440 rv += uint32_size (len) + len;
443 case PROTOBUF_C_TYPE_MESSAGE:
444 for (i = 0; i < count; i++)
446 size_t len = protobuf_c_message_get_packed_size (((ProtobufCMessage **) array)[i]);
447 rv += uint32_size (len) + len;
450 //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
453 header_size += uint32_size (rv);
454 return header_size + rv;
457 /* Get the packed size of a unknown field (meaning one that
458 is passed through mostly uninterpreted... this is done
459 for forward compatibilty with the addition of new fields). */
461 unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field)
463 return get_tag_size (field->tag) + field->len;
466 /* Get the number of bytes that the message will occupy once serialized. */
468 protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
472 ASSERT_IS_MESSAGE (message);
473 for (i = 0; i < message->descriptor->n_fields; i++)
475 const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
476 const void *member = ((const char *) message) + field->offset;
477 const void *qmember = ((const char *) message) + field->quantifier_offset;
479 if (field->label == PROTOBUF_C_LABEL_REQUIRED)
480 rv += required_field_get_packed_size (field, member);
481 else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
482 rv += optional_field_get_packed_size (field, qmember, member);
484 rv += repeated_field_get_packed_size (field, * (const size_t *) qmember, member);
486 for (i = 0; i < message->n_unknown_fields; i++)
487 rv += unknown_field_get_packed_size (&message->unknown_fields[i]);
491 /* Pack an unsigned 32-bit integer in base-128 encoding, and return the number of bytes needed:
492 this will be 5 or less. */
494 uint32_pack (uint32_t value, uint8_t *out)
499 out[rv++] = value | 0x80;
503 out[rv++] = value | 0x80;
507 out[rv++] = value | 0x80;
511 out[rv++] = value | 0x80;
517 /* assert: value<128 */
522 /* Pack a 32-bit signed integer, returning the number of bytes needed.
523 Negative numbers are packed as twos-complement 64-bit integers. */
525 int32_pack (int32_t value, uint8_t *out)
529 out[0] = value | 0x80;
530 out[1] = (value>>7) | 0x80;
531 out[2] = (value>>14) | 0x80;
532 out[3] = (value>>21) | 0x80;
533 out[4] = (value>>28) | 0x80;
534 out[5] = out[6] = out[7] = out[8] = 0xff;
539 return uint32_pack (value, out);
542 /* Pack a 32-bit integer in zigwag encoding. */
544 sint32_pack (int32_t value, uint8_t *out)
546 return uint32_pack (zigzag32 (value), out);
549 /* Pack a 64-bit unsigned integer that fits in a 64-bit uint,
550 using base-128 encoding. */
552 uint64_pack (uint64_t value, uint8_t *out)
554 uint32_t hi = value>>32;
558 return uint32_pack ((uint32_t)lo, out);
559 out[0] = (lo) | 0x80;
560 out[1] = (lo>>7) | 0x80;
561 out[2] = (lo>>14) | 0x80;
562 out[3] = (lo>>21) | 0x80;
565 out[4] = (hi<<4) | (lo>>28);
570 out[4] = ((hi&7)<<4) | (lo>>28) | 0x80;
576 out[rv++] = hi | 0x80;
583 /* Pack a 64-bit signed integer in zigzan encoding,
584 return the size of the packed output.
585 (Max returned value is 10) */
587 sint64_pack (int64_t value, uint8_t *out)
589 return uint64_pack (zigzag64 (value), out);
592 /* Pack a 32-bit value, little-endian.
593 Used for fixed32, sfixed32, float) */
595 fixed32_pack (uint32_t value, uint8_t *out)
598 memcpy (out, &value, 4);
608 /* Pack a 64-bit fixed-length value.
609 (Used for fixed64, sfixed64, double) */
610 /* XXX: the big-endian impl is really only good for 32-bit machines,
611 a 64-bit version would be appreciated, plus a way
612 to decide to use 64-bit math where convenient. */
614 fixed64_pack (uint64_t value, uint8_t *out)
617 memcpy (out, &value, 8);
619 fixed32_pack (value, out);
620 fixed32_pack (value>>32, out+4);
626 /* Pack a boolean as 0 or 1, even though the protobuf_c_boolean
627 can really assume any integer value. */
628 /* XXX: perhaps on some platforms "*out = !!value" would be
629 a better impl, b/c that is idiotmatic c++ in some stl impls. */
631 boolean_pack (protobuf_c_boolean value, uint8_t *out)
633 *out = value ? 1 : 0;
637 /* Pack a length-prefixed string.
638 The input string is NUL-terminated.
640 The NULL pointer is treated as an empty string.
641 This isn't really necessary, but it allows people
642 to leave required strings blank.
643 (See Issue 13 in the bug tracker for a
644 little more explanation).
647 string_pack (const char * str, uint8_t *out)
656 size_t len = strlen (str);
657 size_t rv = uint32_pack (len, out);
658 memcpy (out + rv, str, len);
664 binary_data_pack (const ProtobufCBinaryData *bd, uint8_t *out)
666 size_t len = bd->len;
667 size_t rv = uint32_pack (len, out);
668 memcpy (out + rv, bd->data, len);
673 prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out)
682 size_t rv = protobuf_c_message_pack (message, out + 1);
683 uint32_t rv_packed_size = uint32_size (rv);
684 if (rv_packed_size != 1)
685 memmove (out + rv_packed_size, out + 1, rv);
686 return uint32_pack (rv, out) + rv;
690 /* wire-type will be added in required_field_pack() */
691 /* XXX: just call uint64_pack on 64-bit platforms. */
693 tag_pack (uint32_t id, uint8_t *out)
695 if (id < (1<<(32-3)))
696 return uint32_pack (id<<3, out);
698 return uint64_pack (((uint64_t)id) << 3, out);
702 required_field_pack (const ProtobufCFieldDescriptor *field,
706 size_t rv = tag_pack (field->id, out);
709 case PROTOBUF_C_TYPE_SINT32:
710 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
711 return rv + sint32_pack (*(const int32_t *) member, out + rv);
712 case PROTOBUF_C_TYPE_INT32:
713 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
714 return rv + int32_pack (*(const uint32_t *) member, out + rv);
715 case PROTOBUF_C_TYPE_UINT32:
716 case PROTOBUF_C_TYPE_ENUM:
717 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
718 return rv + uint32_pack (*(const uint32_t *) member, out + rv);
719 case PROTOBUF_C_TYPE_SINT64:
720 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
721 return rv + sint64_pack (*(const int64_t *) member, out + rv);
722 case PROTOBUF_C_TYPE_INT64:
723 case PROTOBUF_C_TYPE_UINT64:
724 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
725 return rv + uint64_pack (*(const uint64_t *) member, out + rv);
726 case PROTOBUF_C_TYPE_SFIXED32:
727 case PROTOBUF_C_TYPE_FIXED32:
728 case PROTOBUF_C_TYPE_FLOAT:
729 out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
730 return rv + fixed32_pack (*(const uint32_t *) member, out + rv);
731 case PROTOBUF_C_TYPE_SFIXED64:
732 case PROTOBUF_C_TYPE_FIXED64:
733 case PROTOBUF_C_TYPE_DOUBLE:
734 out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
735 return rv + fixed64_pack (*(const uint64_t *) member, out + rv);
736 case PROTOBUF_C_TYPE_BOOL:
737 out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
738 return rv + boolean_pack (*(const protobuf_c_boolean *) member, out + rv);
739 case PROTOBUF_C_TYPE_STRING:
741 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
742 return rv + string_pack (*(char * const *) member, out + rv);
745 case PROTOBUF_C_TYPE_BYTES:
747 const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
748 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
749 return rv + binary_data_pack (bd, out + rv);
751 //case PROTOBUF_C_TYPE_GROUP: // NOT SUPPORTED
752 case PROTOBUF_C_TYPE_MESSAGE:
754 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
755 return rv + prefixed_message_pack (*(ProtobufCMessage * const *) member,
759 PROTOBUF_C_ASSERT_NOT_REACHED ();
763 optional_field_pack (const ProtobufCFieldDescriptor *field,
764 const protobuf_c_boolean *has,
768 if (field->type == PROTOBUF_C_TYPE_MESSAGE
769 || field->type == PROTOBUF_C_TYPE_STRING)
771 const void *ptr = * (const void * const *) member;
773 || ptr == field->default_value)
781 return required_field_pack (field, member, out);
784 /* TODO: implement as a table lookup */
786 sizeof_elt_in_repeated_array (ProtobufCType type)
790 case PROTOBUF_C_TYPE_SINT32:
791 case PROTOBUF_C_TYPE_INT32:
792 case PROTOBUF_C_TYPE_UINT32:
793 case PROTOBUF_C_TYPE_SFIXED32:
794 case PROTOBUF_C_TYPE_FIXED32:
795 case PROTOBUF_C_TYPE_FLOAT:
796 case PROTOBUF_C_TYPE_ENUM:
798 case PROTOBUF_C_TYPE_SINT64:
799 case PROTOBUF_C_TYPE_INT64:
800 case PROTOBUF_C_TYPE_UINT64:
801 case PROTOBUF_C_TYPE_SFIXED64:
802 case PROTOBUF_C_TYPE_FIXED64:
803 case PROTOBUF_C_TYPE_DOUBLE:
805 case PROTOBUF_C_TYPE_BOOL:
806 return sizeof (protobuf_c_boolean);
807 case PROTOBUF_C_TYPE_STRING:
808 case PROTOBUF_C_TYPE_MESSAGE:
809 return sizeof (void *);
810 case PROTOBUF_C_TYPE_BYTES:
811 return sizeof (ProtobufCBinaryData);
813 PROTOBUF_C_ASSERT_NOT_REACHED ();
818 copy_to_little_endian_32 (void *out, const void *in, unsigned N)
821 memcpy (out, in, N * 4);
824 const uint32_t *ini = in;
825 for (i = 0; i < N; i++)
826 fixed32_pack (ini[i], (uint32_t*)out + i);
830 copy_to_little_endian_64 (void *out, const void *in, unsigned N)
833 memcpy (out, in, N * 8);
836 const uint64_t *ini = in;
837 for (i = 0; i < N; i++)
838 fixed64_pack (ini[i], (uint64_t*)out + i);
843 get_type_min_size (ProtobufCType type)
845 if (type == PROTOBUF_C_TYPE_SFIXED32
846 || type == PROTOBUF_C_TYPE_FIXED32
847 || type == PROTOBUF_C_TYPE_FLOAT)
849 if (type == PROTOBUF_C_TYPE_SFIXED64
850 || type == PROTOBUF_C_TYPE_FIXED64
851 || type == PROTOBUF_C_TYPE_DOUBLE)
857 repeated_field_pack (const ProtobufCFieldDescriptor *field,
862 char *array = * (char * const *) member;
869 unsigned payload_len;
870 unsigned length_size_min;
871 unsigned actual_length_size;
875 header_len = tag_pack (field->id, out);
876 out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
877 len_start = header_len;
878 min_length = get_type_min_size (field->type) * count;
879 length_size_min = uint32_size (min_length);
880 header_len += length_size_min;
881 payload_at = out + header_len;
884 case PROTOBUF_C_TYPE_SFIXED32:
885 case PROTOBUF_C_TYPE_FIXED32:
886 case PROTOBUF_C_TYPE_FLOAT:
887 copy_to_little_endian_32 (payload_at, array, count);
888 payload_at += count * 4;
891 case PROTOBUF_C_TYPE_SFIXED64:
892 case PROTOBUF_C_TYPE_FIXED64:
893 case PROTOBUF_C_TYPE_DOUBLE:
894 copy_to_little_endian_64 (payload_at, array, count);
895 payload_at += count * 8;
898 case PROTOBUF_C_TYPE_INT32:
900 const int32_t *arr = (const int32_t *) array;
901 for (i = 0; i < count; i++)
902 payload_at += int32_pack (arr[i], payload_at);
906 case PROTOBUF_C_TYPE_SINT32:
908 const int32_t *arr = (const int32_t *) array;
909 for (i = 0; i < count; i++)
910 payload_at += sint32_pack (arr[i], payload_at);
914 case PROTOBUF_C_TYPE_SINT64:
916 const int64_t *arr = (const int64_t *) array;
917 for (i = 0; i < count; i++)
918 payload_at += sint64_pack (arr[i], payload_at);
921 case PROTOBUF_C_TYPE_ENUM:
922 case PROTOBUF_C_TYPE_UINT32:
924 const uint32_t *arr = (const uint32_t *) array;
925 for (i = 0; i < count; i++)
926 payload_at += uint32_pack (arr[i], payload_at);
929 case PROTOBUF_C_TYPE_INT64:
930 case PROTOBUF_C_TYPE_UINT64:
932 const uint64_t *arr = (const uint64_t *) array;
933 for (i = 0; i < count; i++)
934 payload_at += uint64_pack (arr[i], payload_at);
937 case PROTOBUF_C_TYPE_BOOL:
939 const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
940 for (i = 0; i < count; i++)
941 payload_at += boolean_pack (arr[i], payload_at);
948 payload_len = payload_at - (out + header_len);
949 actual_length_size = uint32_size (payload_len);
950 if (length_size_min != actual_length_size)
952 assert (actual_length_size == length_size_min + 1);
953 memmove (out + header_len + 1, out + header_len, payload_len);
956 uint32_pack (payload_len, out + len_start);
957 return header_len + payload_len;
961 /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
963 unsigned siz = sizeof_elt_in_repeated_array (field->type);
964 for (i = 0; i < count; i++)
966 rv += required_field_pack (field, array, out + rv);
973 unknown_field_pack (const ProtobufCMessageUnknownField *field,
976 size_t rv = tag_pack (field->tag, out);
977 out[0] |= field->wire_type;
978 memcpy (out + rv, field->data, field->len);
979 return rv + field->len;
983 protobuf_c_message_pack (const ProtobufCMessage *message,
988 ASSERT_IS_MESSAGE (message);
989 for (i = 0; i < message->descriptor->n_fields; i++)
991 const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
992 const void *member = ((const char *) message) + field->offset;
994 /* it doesn't hurt to compute qmember (a pointer to the quantifier
995 field of the structure), but the pointer is only valid if
998 - an optional field that isn't a pointer type
999 (meaning: not a message or a string) */
1000 const void *qmember = ((const char *) message) + field->quantifier_offset;
1002 if (field->label == PROTOBUF_C_LABEL_REQUIRED)
1003 rv += required_field_pack (field, member, out + rv);
1004 else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
1005 /* note that qmember is bogus for strings and messages,
1006 but it isn't used */
1007 rv += optional_field_pack (field, qmember, member, out + rv);
1009 rv += repeated_field_pack (field, * (const size_t *) qmember, member, out + rv);
1011 for (i = 0; i < message->n_unknown_fields; i++)
1012 rv += unknown_field_pack (&message->unknown_fields[i], out + rv);
1016 /* === pack_to_buffer() === */
1018 required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1020 ProtobufCBuffer *buffer)
1023 uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1024 rv = tag_pack (field->id, scratch);
1025 switch (field->type)
1027 case PROTOBUF_C_TYPE_SINT32:
1028 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1029 rv += sint32_pack (*(const int32_t *) member, scratch + rv);
1030 buffer->append (buffer, rv, scratch);
1032 case PROTOBUF_C_TYPE_INT32:
1033 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1034 rv += int32_pack (*(const uint32_t *) member, scratch + rv);
1035 buffer->append (buffer, rv, scratch);
1037 case PROTOBUF_C_TYPE_UINT32:
1038 case PROTOBUF_C_TYPE_ENUM:
1039 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1040 rv += uint32_pack (*(const uint32_t *) member, scratch + rv);
1041 buffer->append (buffer, rv, scratch);
1043 case PROTOBUF_C_TYPE_SINT64:
1044 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1045 rv += sint64_pack (*(const int64_t *) member, scratch + rv);
1046 buffer->append (buffer, rv, scratch);
1048 case PROTOBUF_C_TYPE_INT64:
1049 case PROTOBUF_C_TYPE_UINT64:
1050 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1051 rv += uint64_pack (*(const uint64_t *) member, scratch + rv);
1052 buffer->append (buffer, rv, scratch);
1054 case PROTOBUF_C_TYPE_SFIXED32:
1055 case PROTOBUF_C_TYPE_FIXED32:
1056 case PROTOBUF_C_TYPE_FLOAT:
1057 scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1058 rv += fixed32_pack (*(const uint32_t *) member, scratch + rv);
1059 buffer->append (buffer, rv, scratch);
1061 case PROTOBUF_C_TYPE_SFIXED64:
1062 case PROTOBUF_C_TYPE_FIXED64:
1063 case PROTOBUF_C_TYPE_DOUBLE:
1064 scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1065 rv += fixed64_pack (*(const uint64_t *) member, scratch + rv);
1066 buffer->append (buffer, rv, scratch);
1068 case PROTOBUF_C_TYPE_BOOL:
1069 scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1070 rv += boolean_pack (*(const protobuf_c_boolean *) member, scratch + rv);
1071 buffer->append (buffer, rv, scratch);
1073 case PROTOBUF_C_TYPE_STRING:
1075 const char *str = *(char * const *) member;
1076 size_t sublen = str ? strlen (str) : 0;
1077 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1078 rv += uint32_pack (sublen, scratch + rv);
1079 buffer->append (buffer, rv, scratch);
1080 buffer->append (buffer, sublen, (const uint8_t *) str);
1085 case PROTOBUF_C_TYPE_BYTES:
1087 const ProtobufCBinaryData * bd = ((const ProtobufCBinaryData*) member);
1088 size_t sublen = bd->len;
1089 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1090 rv += uint32_pack (sublen, scratch + rv);
1091 buffer->append (buffer, rv, scratch);
1092 buffer->append (buffer, sublen, bd->data);
1096 //PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
1097 case PROTOBUF_C_TYPE_MESSAGE:
1099 uint8_t simple_buffer_scratch[256];
1101 ProtobufCBufferSimple simple_buffer
1102 = PROTOBUF_C_BUFFER_SIMPLE_INIT (simple_buffer_scratch);
1103 const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1104 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1108 sublen = protobuf_c_message_pack_to_buffer (msg, &simple_buffer.base);
1109 rv += uint32_pack (sublen, scratch + rv);
1110 buffer->append (buffer, rv, scratch);
1111 buffer->append (buffer, sublen, simple_buffer.data);
1113 PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&simple_buffer);
1117 PROTOBUF_C_ASSERT_NOT_REACHED ();
1122 optional_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1123 const protobuf_c_boolean *has,
1125 ProtobufCBuffer *buffer)
1127 if (field->type == PROTOBUF_C_TYPE_MESSAGE
1128 || field->type == PROTOBUF_C_TYPE_STRING)
1130 const void *ptr = * (const void * const *) member;
1132 || ptr == field->default_value)
1140 return required_field_pack_to_buffer (field, member, buffer);
1144 get_packed_payload_length (const ProtobufCFieldDescriptor *field,
1150 switch (field->type)
1152 case PROTOBUF_C_TYPE_SFIXED32:
1153 case PROTOBUF_C_TYPE_FIXED32:
1154 case PROTOBUF_C_TYPE_FLOAT:
1157 case PROTOBUF_C_TYPE_SFIXED64:
1158 case PROTOBUF_C_TYPE_FIXED64:
1159 case PROTOBUF_C_TYPE_DOUBLE:
1162 case PROTOBUF_C_TYPE_INT32:
1164 const int32_t *arr = (const int32_t *) array;
1165 for (i = 0; i < count; i++)
1166 rv += int32_size (arr[i]);
1170 case PROTOBUF_C_TYPE_SINT32:
1172 const int32_t *arr = (const int32_t *) array;
1173 for (i = 0; i < count; i++)
1174 rv += sint32_size (arr[i]);
1177 case PROTOBUF_C_TYPE_ENUM:
1178 case PROTOBUF_C_TYPE_UINT32:
1180 const uint32_t *arr = (const uint32_t *) array;
1181 for (i = 0; i < count; i++)
1182 rv += uint32_size (arr[i]);
1186 case PROTOBUF_C_TYPE_SINT64:
1188 const int64_t *arr = (const int64_t *) array;
1189 for (i = 0; i < count; i++)
1190 rv += sint64_size (arr[i]);
1193 case PROTOBUF_C_TYPE_INT64:
1194 case PROTOBUF_C_TYPE_UINT64:
1196 const uint64_t *arr = (const uint64_t *) array;
1197 for (i = 0; i < count; i++)
1198 rv += uint64_size (arr[i]);
1201 case PROTOBUF_C_TYPE_BOOL:
1209 pack_buffer_packed_payload (const ProtobufCFieldDescriptor *field,
1212 ProtobufCBuffer *buffer)
1214 uint8_t scratch[16];
1217 switch (field->type)
1219 case PROTOBUF_C_TYPE_SFIXED32:
1220 case PROTOBUF_C_TYPE_FIXED32:
1221 case PROTOBUF_C_TYPE_FLOAT:
1222 #if IS_LITTLE_ENDIAN
1224 goto no_packing_needed;
1226 for (i = 0; i < count; i++)
1228 unsigned len = fixed32_pack (((uint32_t*)array)[i], scratch);
1229 buffer->append (buffer, len, scratch);
1234 case PROTOBUF_C_TYPE_SFIXED64:
1235 case PROTOBUF_C_TYPE_FIXED64:
1236 case PROTOBUF_C_TYPE_DOUBLE:
1237 #if IS_LITTLE_ENDIAN
1239 goto no_packing_needed;
1241 for (i = 0; i < count; i++)
1243 unsigned len = fixed64_pack (((uint64_t*)array)[i], scratch);
1244 buffer->append (buffer, len, scratch);
1249 case PROTOBUF_C_TYPE_INT32:
1250 for (i = 0; i < count; i++)
1252 unsigned len = int32_pack (((int32_t*)array)[i], scratch);
1253 buffer->append (buffer, len, scratch);
1258 case PROTOBUF_C_TYPE_SINT32:
1259 for (i = 0; i < count; i++)
1261 unsigned len = sint32_pack (((int32_t*)array)[i], scratch);
1262 buffer->append (buffer, len, scratch);
1266 case PROTOBUF_C_TYPE_ENUM:
1267 case PROTOBUF_C_TYPE_UINT32:
1268 for (i = 0; i < count; i++)
1270 unsigned len = uint32_pack (((uint32_t*)array)[i], scratch);
1271 buffer->append (buffer, len, scratch);
1276 case PROTOBUF_C_TYPE_SINT64:
1277 for (i = 0; i < count; i++)
1279 unsigned len = sint64_pack (((int64_t*)array)[i], scratch);
1280 buffer->append (buffer, len, scratch);
1284 case PROTOBUF_C_TYPE_INT64:
1285 case PROTOBUF_C_TYPE_UINT64:
1286 for (i = 0; i < count; i++)
1288 unsigned len = uint64_pack (((uint64_t*)array)[i], scratch);
1289 buffer->append (buffer, len, scratch);
1293 case PROTOBUF_C_TYPE_BOOL:
1294 for (i = 0; i < count; i++)
1296 unsigned len = boolean_pack (((protobuf_c_boolean*)array)[i], scratch);
1297 buffer->append (buffer, len, scratch);
1307 buffer->append (buffer, rv, array);
1312 repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1315 ProtobufCBuffer *buffer)
1317 char *array = * (char * const *) member;
1322 uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1323 size_t rv = tag_pack (field->id, scratch);
1324 size_t payload_len = get_packed_payload_length (field, count, array);
1326 scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1327 rv += uint32_pack (payload_len, scratch + rv);
1328 buffer->append (buffer, rv, scratch);
1329 tmp = pack_buffer_packed_payload (field, count, array, buffer);
1330 assert (tmp == payload_len);
1331 return rv + payload_len;
1337 /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1339 siz = sizeof_elt_in_repeated_array (field->type);
1340 for (i = 0; i < count; i++)
1342 rv += required_field_pack_to_buffer (field, array, buffer);
1350 unknown_field_pack_to_buffer (const ProtobufCMessageUnknownField *field,
1351 ProtobufCBuffer *buffer)
1353 uint8_t header[MAX_UINT64_ENCODED_SIZE];
1354 size_t rv = tag_pack (field->tag, header);
1355 header[0] |= field->wire_type;
1356 buffer->append (buffer, rv, header);
1357 buffer->append (buffer, field->len, field->data);
1358 return rv + field->len;
1362 protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
1363 ProtobufCBuffer *buffer)
1367 ASSERT_IS_MESSAGE (message);
1368 for (i = 0; i < message->descriptor->n_fields; i++)
1370 const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
1371 const void *member = ((const char *) message) + field->offset;
1372 const void *qmember = ((const char *) message) + field->quantifier_offset;
1374 if (field->label == PROTOBUF_C_LABEL_REQUIRED)
1375 rv += required_field_pack_to_buffer (field, member, buffer);
1376 else if (field->label == PROTOBUF_C_LABEL_OPTIONAL)
1377 rv += optional_field_pack_to_buffer (field, qmember, member, buffer);
1379 rv += repeated_field_pack_to_buffer (field, * (const size_t *) qmember, member, buffer);
1381 for (i = 0; i < message->n_unknown_fields; i++)
1382 rv += unknown_field_pack_to_buffer (&message->unknown_fields[i], buffer);
1387 /* === unpacking === */
1388 #if PRINT_UNPACK_ERRORS
1389 # define UNPACK_ERROR(args) do { printf args;printf("\n"); }while(0)
1391 # define UNPACK_ERROR(args) do { } while (0)
1395 int_range_lookup (unsigned n_ranges,
1396 const ProtobufCIntRange *ranges,
1406 unsigned mid = start + n / 2;
1407 if (value < ranges[mid].start_value)
1411 else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
1413 unsigned new_start = mid + 1;
1414 n = start + n - new_start;
1418 return (value - ranges[mid].start_value) + ranges[mid].orig_index;
1422 unsigned start_orig_index = ranges[start].orig_index;
1423 unsigned range_size = ranges[start+1].orig_index - start_orig_index;
1425 if (ranges[start].start_value <= value
1426 && value < (int)(ranges[start].start_value + range_size))
1427 return (value - ranges[start].start_value) + start_orig_index;
1433 parse_tag_and_wiretype (size_t len,
1434 const uint8_t *data,
1436 ProtobufCWireType *wiretype_out)
1438 unsigned max_rv = len > 5 ? 5 : len;
1439 uint32_t tag = (data[0]&0x7f) >> 3;
1442 *wiretype_out = data[0] & 7;
1443 if ((data[0] & 0x80) == 0)
1448 for (rv = 1; rv < max_rv; rv++)
1449 if (data[rv] & 0x80)
1451 tag |= (data[rv] & 0x7f) << shift;
1456 tag |= data[rv] << shift;
1460 return 0; /* error: bad header */
1463 /* sizeof(ScannedMember) must be <= (1<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
1464 #define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
1465 typedef struct _ScannedMember ScannedMember;
1466 struct _ScannedMember
1470 uint8_t length_prefix_len;
1471 const ProtobufCFieldDescriptor *field;
1473 const uint8_t *data;
1476 static inline uint32_t
1477 scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out)
1479 unsigned hdr_max = len < 5 ? len : 5;
1484 for (i = 0; i < hdr_max; i++)
1486 val |= (data[i] & 0x7f) << shift;
1488 if ((data[i] & 0x80) == 0)
1493 UNPACK_ERROR (("error parsing length for length-prefixed data"));
1497 *prefix_len_out = hdr_len;
1498 if (hdr_len + val > len)
1500 UNPACK_ERROR (("data too short after length-prefix of %u",
1504 return hdr_len + val;
1508 max_b128_numbers (size_t len, const uint8_t *data)
1512 if ((*data++ & 0x80) == 0)
1518 /* Given a raw slab of packed-repeated values,
1519 determine the number of elements.
1520 This function detects certain kinds of errors
1521 but not others; the remaining error checking is done by
1522 parse_packed_repeated_member() */
1523 static protobuf_c_boolean
1524 count_packed_elements (ProtobufCType type,
1526 const uint8_t *data,
1531 case PROTOBUF_C_TYPE_SFIXED32:
1532 case PROTOBUF_C_TYPE_FIXED32:
1533 case PROTOBUF_C_TYPE_FLOAT:
1536 UNPACK_ERROR (("length must be a multiple of 4 for fixed-length 32-bit types"));
1539 *count_out = len / 4;
1542 case PROTOBUF_C_TYPE_SFIXED64:
1543 case PROTOBUF_C_TYPE_FIXED64:
1544 case PROTOBUF_C_TYPE_DOUBLE:
1547 UNPACK_ERROR (("length must be a multiple of 8 for fixed-length 64-bit types"));
1550 *count_out = len / 8;
1553 case PROTOBUF_C_TYPE_INT32:
1554 case PROTOBUF_C_TYPE_SINT32:
1555 case PROTOBUF_C_TYPE_ENUM:
1556 case PROTOBUF_C_TYPE_UINT32:
1557 case PROTOBUF_C_TYPE_INT64:
1558 case PROTOBUF_C_TYPE_SINT64:
1559 case PROTOBUF_C_TYPE_UINT64:
1560 *count_out = max_b128_numbers (len, data);
1562 case PROTOBUF_C_TYPE_BOOL:
1566 case PROTOBUF_C_TYPE_STRING:
1567 case PROTOBUF_C_TYPE_BYTES:
1568 case PROTOBUF_C_TYPE_MESSAGE:
1570 UNPACK_ERROR (("bad protobuf-c type %u for packed-repeated", type));
1575 static inline uint32_t
1576 parse_uint32 (unsigned len, const uint8_t *data)
1578 unsigned rv = data[0] & 0x7f;
1581 rv |= ((data[1] & 0x7f) << 7);
1584 rv |= ((data[2] & 0x7f) << 14);
1587 rv |= ((data[3] & 0x7f) << 21);
1589 rv |= (data[4] << 28);
1595 static inline uint32_t
1596 parse_int32 (unsigned len, const uint8_t *data)
1598 return parse_uint32 (len, data);
1600 static inline int32_t
1601 unzigzag32 (uint32_t v)
1608 static inline uint32_t
1609 parse_fixed_uint32 (const uint8_t *data)
1611 #if IS_LITTLE_ENDIAN
1613 memcpy (&t, data, 4);
1616 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
1620 parse_uint64 (unsigned len, const uint8_t *data)
1624 return parse_uint32 (len, data);
1625 uint64_t rv = ((data[0] & 0x7f))
1626 | ((data[1] & 0x7f)<<7)
1627 | ((data[2] & 0x7f)<<14)
1628 | ((data[3] & 0x7f)<<21);
1630 for (i = 4; i < len; i++)
1632 rv |= (((uint64_t)(data[i]&0x7f)) << shift);
1637 static inline int64_t
1638 unzigzag64 (uint64_t v)
1645 static inline uint64_t
1646 parse_fixed_uint64 (const uint8_t *data)
1648 #if IS_LITTLE_ENDIAN
1650 memcpy (&t, data, 8);
1653 return (uint64_t)parse_fixed_uint32 (data)
1654 | (((uint64_t)parse_fixed_uint32(data+4)) << 32);
1657 static protobuf_c_boolean
1658 parse_boolean (unsigned len, const uint8_t *data)
1661 for (i = 0; i < len; i++)
1666 static protobuf_c_boolean
1667 parse_required_member (ScannedMember *scanned_member,
1669 ProtobufCAllocator *allocator,
1670 protobuf_c_boolean maybe_clear)
1672 unsigned len = scanned_member->len;
1673 const uint8_t *data = scanned_member->data;
1674 ProtobufCWireType wire_type = scanned_member->wire_type;
1675 switch (scanned_member->field->type)
1677 case PROTOBUF_C_TYPE_INT32:
1678 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1680 *(uint32_t*)member = parse_int32 (len, data);
1682 case PROTOBUF_C_TYPE_UINT32:
1683 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1685 *(uint32_t*)member = parse_uint32 (len, data);
1687 case PROTOBUF_C_TYPE_SINT32:
1688 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1690 *(int32_t*)member = unzigzag32 (parse_uint32 (len, data));
1692 case PROTOBUF_C_TYPE_SFIXED32:
1693 case PROTOBUF_C_TYPE_FIXED32:
1694 case PROTOBUF_C_TYPE_FLOAT:
1695 if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
1697 *(uint32_t*)member = parse_fixed_uint32 (data);
1700 case PROTOBUF_C_TYPE_INT64:
1701 case PROTOBUF_C_TYPE_UINT64:
1702 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1704 *(uint64_t*)member = parse_uint64 (len, data);
1706 case PROTOBUF_C_TYPE_SINT64:
1707 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1709 *(int64_t*)member = unzigzag64 (parse_uint64 (len, data));
1711 case PROTOBUF_C_TYPE_SFIXED64:
1712 case PROTOBUF_C_TYPE_FIXED64:
1713 case PROTOBUF_C_TYPE_DOUBLE:
1714 if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
1716 *(uint64_t*)member = parse_fixed_uint64 (data);
1719 case PROTOBUF_C_TYPE_BOOL:
1720 *(protobuf_c_boolean*)member = parse_boolean (len, data);
1723 case PROTOBUF_C_TYPE_ENUM:
1724 if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1726 *(uint32_t*)member = parse_uint32 (len, data);
1729 case PROTOBUF_C_TYPE_STRING:
1730 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1733 char **pstr = member;
1734 unsigned pref_len = scanned_member->length_prefix_len;
1735 if (maybe_clear && *pstr != NULL)
1737 const char *def = scanned_member->field->default_value;
1738 if (*pstr != NULL && *pstr != def)
1739 FREE (allocator, *pstr);
1741 DO_ALLOC (*pstr, allocator, len - pref_len + 1, return 0);
1742 memcpy (*pstr, data + pref_len, len - pref_len);
1743 (*pstr)[len-pref_len] = 0;
1746 case PROTOBUF_C_TYPE_BYTES:
1747 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1750 ProtobufCBinaryData *bd = member;
1751 const ProtobufCBinaryData *def_bd;
1752 unsigned pref_len = scanned_member->length_prefix_len;
1753 def_bd = scanned_member->field->default_value;
1754 if (maybe_clear && bd->data != NULL && bd->data != def_bd->data)
1755 FREE (allocator, bd->data);
1756 DO_ALLOC (bd->data, allocator, len - pref_len, return 0);
1757 memcpy (bd->data, data + pref_len, len - pref_len);
1758 bd->len = len - pref_len;
1761 //case PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
1762 case PROTOBUF_C_TYPE_MESSAGE:
1763 if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1766 ProtobufCMessage **pmessage = member;
1767 ProtobufCMessage *subm;
1768 const ProtobufCMessage *def_mess;
1769 unsigned pref_len = scanned_member->length_prefix_len;
1770 def_mess = scanned_member->field->default_value;
1771 if (maybe_clear && *pmessage != NULL && *pmessage != def_mess)
1772 protobuf_c_message_free_unpacked (*pmessage, allocator);
1773 subm = protobuf_c_message_unpack (scanned_member->field->descriptor,
1775 len - pref_len, data + pref_len);
1776 *pmessage = subm; /* since we freed the message we must clear the field, even if NULL */
1785 static protobuf_c_boolean
1786 parse_optional_member (ScannedMember *scanned_member,
1788 ProtobufCMessage *message,
1789 ProtobufCAllocator *allocator)
1791 if (!parse_required_member (scanned_member, member, allocator, TRUE))
1793 if (scanned_member->field->quantifier_offset != 0)
1794 STRUCT_MEMBER (protobuf_c_boolean,
1796 scanned_member->field->quantifier_offset) = 1;
1800 static protobuf_c_boolean
1801 parse_repeated_member (ScannedMember *scanned_member,
1803 ProtobufCMessage *message,
1804 ProtobufCAllocator *allocator)
1806 const ProtobufCFieldDescriptor *field = scanned_member->field;
1807 size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
1808 size_t siz = sizeof_elt_in_repeated_array (field->type);
1809 char *array = *(char**)member;
1810 if (!parse_required_member (scanned_member,
1811 array + siz * (*p_n),
1819 static unsigned scan_varint (unsigned len, const uint8_t *data)
1824 for (i = 0; i < len; i++)
1825 if ((data[i] & 0x80) == 0)
1832 static protobuf_c_boolean
1833 parse_packed_repeated_member (ScannedMember *scanned_member,
1835 ProtobufCMessage *message)
1837 const ProtobufCFieldDescriptor *field = scanned_member->field;
1838 size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
1839 size_t siz = sizeof_elt_in_repeated_array (field->type);
1840 char *array = *(char**)member + siz * (*p_n);
1841 const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
1842 size_t rem = scanned_member->len - scanned_member->length_prefix_len;
1845 switch (field->type)
1847 case PROTOBUF_C_TYPE_SFIXED32:
1848 case PROTOBUF_C_TYPE_FIXED32:
1849 case PROTOBUF_C_TYPE_FLOAT:
1850 count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
1851 #if IS_LITTLE_ENDIAN
1852 goto no_unpacking_needed;
1854 for (i = 0; i < count; i++)
1856 ((uint32_t*)array)[i] = parse_fixed_uint32 (at);
1861 case PROTOBUF_C_TYPE_SFIXED64:
1862 case PROTOBUF_C_TYPE_FIXED64:
1863 case PROTOBUF_C_TYPE_DOUBLE:
1864 count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
1865 #if IS_LITTLE_ENDIAN
1866 goto no_unpacking_needed;
1868 for (i = 0; i < count; i++)
1870 ((uint64_t*)array)[i] = parse_fixed_uint64 (at);
1875 case PROTOBUF_C_TYPE_INT32:
1878 unsigned s = scan_varint (rem, at);
1881 UNPACK_ERROR (("bad packed-repeated int32 value"));
1884 ((int32_t*)array)[count++] = parse_int32 (s, at);
1890 case PROTOBUF_C_TYPE_SINT32:
1893 unsigned s = scan_varint (rem, at);
1896 UNPACK_ERROR (("bad packed-repeated sint32 value"));
1899 ((int32_t*)array)[count++] = unzigzag32 (parse_uint32 (s, at));
1904 case PROTOBUF_C_TYPE_ENUM:
1905 case PROTOBUF_C_TYPE_UINT32:
1908 unsigned s = scan_varint (rem, at);
1911 UNPACK_ERROR (("bad packed-repeated enum or uint32 value"));
1914 ((uint32_t*)array)[count++] = parse_uint32 (s, at);
1920 case PROTOBUF_C_TYPE_SINT64:
1923 unsigned s = scan_varint (rem, at);
1926 UNPACK_ERROR (("bad packed-repeated sint64 value"));
1929 ((int64_t*)array)[count++] = unzigzag64 (parse_uint64 (s, at));
1934 case PROTOBUF_C_TYPE_INT64:
1935 case PROTOBUF_C_TYPE_UINT64:
1938 unsigned s = scan_varint (rem, at);
1941 UNPACK_ERROR (("bad packed-repeated int64/uint64 value"));
1944 ((int64_t*)array)[count++] = parse_uint64 (s, at);
1949 case PROTOBUF_C_TYPE_BOOL:
1951 for (i = 0; i < count; i++)
1955 UNPACK_ERROR (("bad packed-repeated boolean value"));
1958 ((protobuf_c_boolean*)array)[i] = at[i];
1967 no_unpacking_needed:
1968 memcpy (array, at, count * siz);
1973 static protobuf_c_boolean
1974 parse_member (ScannedMember *scanned_member,
1975 ProtobufCMessage *message,
1976 ProtobufCAllocator *allocator)
1978 const ProtobufCFieldDescriptor *field = scanned_member->field;
1982 ProtobufCMessageUnknownField *ufield = message->unknown_fields + (message->n_unknown_fields++);
1983 ufield->tag = scanned_member->tag;
1984 ufield->wire_type = scanned_member->wire_type;
1985 ufield->len = scanned_member->len;
1986 DO_UNALIGNED_ALLOC (ufield->data, allocator, scanned_member->len, return 0);
1987 memcpy (ufield->data, scanned_member->data, ufield->len);
1990 member = (char*)message + field->offset;
1991 switch (field->label)
1993 case PROTOBUF_C_LABEL_REQUIRED:
1994 return parse_required_member (scanned_member, member, allocator, TRUE);
1995 case PROTOBUF_C_LABEL_OPTIONAL:
1996 return parse_optional_member (scanned_member, member, message, allocator);
1997 case PROTOBUF_C_LABEL_REPEATED:
1999 && scanned_member->wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2000 return parse_packed_repeated_member (scanned_member, member, message);
2002 return parse_repeated_member (scanned_member, member, message, allocator);
2004 PROTOBUF_C_ASSERT_NOT_REACHED ();
2009 /* TODO: expose/use this function if desc->message_init==NULL
2010 (which occurs for old code, and may be useful for certain
2011 programatic techniques for generating descriptors). */
2013 protobuf_c_message_init_generic (const ProtobufCMessageDescriptor *desc,
2014 ProtobufCMessage *message)
2017 memset (message, 0, desc->sizeof_message);
2018 message->descriptor = desc;
2019 for (i = 0; i < desc->n_fields; i++)
2020 if (desc->fields[i].default_value != NULL
2021 && desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
2023 void *field = STRUCT_MEMBER_P (message, desc->fields[i].offset);
2024 const void *dv = desc->fields[i].default_value;
2025 switch (desc->fields[i].type)
2027 case PROTOBUF_C_TYPE_INT32:
2028 case PROTOBUF_C_TYPE_SINT32:
2029 case PROTOBUF_C_TYPE_SFIXED32:
2030 case PROTOBUF_C_TYPE_UINT32:
2031 case PROTOBUF_C_TYPE_FIXED32:
2032 case PROTOBUF_C_TYPE_FLOAT:
2033 case PROTOBUF_C_TYPE_ENUM:
2034 memcpy (field, dv, 4);
2037 case PROTOBUF_C_TYPE_INT64:
2038 case PROTOBUF_C_TYPE_SINT64:
2039 case PROTOBUF_C_TYPE_SFIXED64:
2040 case PROTOBUF_C_TYPE_UINT64:
2041 case PROTOBUF_C_TYPE_FIXED64:
2042 case PROTOBUF_C_TYPE_DOUBLE:
2043 memcpy (field, dv, 8);
2046 case PROTOBUF_C_TYPE_BOOL:
2047 memcpy (field, dv, sizeof (protobuf_c_boolean));
2050 case PROTOBUF_C_TYPE_BYTES:
2051 memcpy (field, dv, sizeof (ProtobufCBinaryData));
2054 case PROTOBUF_C_TYPE_STRING:
2055 case PROTOBUF_C_TYPE_MESSAGE:
2056 /* the next line essentially implements a cast from const,
2057 which is totally unavoidable. */
2058 *(const void**)field = dv;
2064 /* ScannedMember slabs (an unpacking implementation detail).
2065 Before doing real unpacking, we first scan through the
2066 elements to see how many there are (for repeated fields),
2067 and which field to use (for non-repeated fields given twice).
2069 * In order to avoid allocations for small messages,
2070 we keep a stack-allocated slab of ScannedMembers of
2071 size FIRST_SCANNED_MEMBER_SLAB_SIZE (16).
2072 After we fill that up, we allocate each slab twice
2073 as large as the previous one. */
2074 #define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
2076 /* The number of slabs, including the stack-allocated ones;
2077 choose the number so that we would overflow if we needed
2078 a slab larger than provided. */
2079 #define MAX_SCANNED_MEMBER_SLAB \
2080 (sizeof(void*)*8 - 1 \
2081 - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
2082 - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
2085 protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
2086 ProtobufCAllocator *allocator,
2088 const uint8_t *data)
2090 ProtobufCMessage *rv;
2092 const uint8_t *at = data;
2093 const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
2094 ScannedMember first_member_slab[1<<FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
2096 /* scanned_member_slabs[i] is an array of arrays of ScannedMember.
2097 The first slab (scanned_member_slabs[0] is just a pointer to
2098 first_member_slab), above. All subsequent slabs will be allocated
2099 using the allocator. */
2100 ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB+1];
2101 unsigned which_slab = 0; /* the slab we are currently populating */
2102 unsigned in_slab_index = 0; /* number of members in the slab */
2103 size_t n_unknown = 0;
2106 unsigned last_field_index = 0;
2107 unsigned long *required_fields_bitmap;
2108 unsigned required_fields_bitmap_len;
2109 static const unsigned word_bits = sizeof(long) * 8;
2111 ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
2113 if (allocator == NULL)
2114 allocator = &protobuf_c_default_allocator;
2116 required_fields_bitmap_len = (desc->n_fields + word_bits - 1) / word_bits;
2117 required_fields_bitmap = alloca(required_fields_bitmap_len * sizeof(long));
2118 memset(required_fields_bitmap, 0, required_fields_bitmap_len * sizeof(long));
2120 DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL);
2121 scanned_member_slabs[0] = first_member_slab;
2123 /* Generated code always defines "message_init".
2124 However, we provide a fallback for (1) users of old protobuf-c
2125 generated-code that do not provide the function,
2126 and (2) descriptors constructed from some other source
2127 (most likely, direct construction from the .proto file) */
2128 if (desc->message_init != NULL)
2129 protobuf_c_message_init (desc, rv);
2131 protobuf_c_message_init_generic (desc, rv);
2136 ProtobufCWireType wire_type;
2137 size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
2138 const ProtobufCFieldDescriptor *field;
2142 UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
2143 (unsigned)(at-data)));
2144 goto error_cleanup_during_scan;
2146 /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
2147 if (last_field->id != tag)
2150 int field_index = int_range_lookup (desc->n_field_ranges,
2153 if (field_index < 0)
2160 field = desc->fields + field_index;
2162 last_field_index = field_index;
2168 if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
2169 required_fields_bitmap[last_field_index / word_bits] |= (1UL << (last_field_index % word_bits));
2174 tmp.wire_type = wire_type;
2179 case PROTOBUF_C_WIRE_TYPE_VARINT:
2181 unsigned max_len = rem < 10 ? rem : 10;
2183 for (i = 0; i < max_len; i++)
2184 if ((at[i] & 0x80) == 0)
2188 UNPACK_ERROR (("unterminated varint at offset %u",
2189 (unsigned)(at-data)));
2190 goto error_cleanup_during_scan;
2195 case PROTOBUF_C_WIRE_TYPE_64BIT:
2198 UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
2199 (unsigned)(at-data)));
2200 goto error_cleanup_during_scan;
2204 case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED:
2207 tmp.len = scan_length_prefixed_data (rem, at, &pref_len);
2210 /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
2211 goto error_cleanup_during_scan;
2213 tmp.length_prefix_len = pref_len;
2216 case PROTOBUF_C_WIRE_TYPE_32BIT:
2219 UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
2220 (unsigned)(at-data)));
2221 goto error_cleanup_during_scan;
2226 UNPACK_ERROR (("unsupported tag %u at offset %u",
2227 wire_type, (unsigned)(at-data)));
2228 goto error_cleanup_during_scan;
2230 if (in_slab_index == (1U<<(which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
2234 if (which_slab == MAX_SCANNED_MEMBER_SLAB)
2236 UNPACK_ERROR (("too many fields"));
2237 goto error_cleanup_during_scan;
2240 size = sizeof(ScannedMember) << (which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
2241 /* TODO: consider using alloca() ! */
2242 if (allocator->tmp_alloc != NULL)
2243 scanned_member_slabs[which_slab] = TMPALLOC(allocator, size);
2245 DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup_during_scan);
2247 scanned_member_slabs[which_slab][in_slab_index++] = tmp;
2249 if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED)
2251 size_t *n = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
2253 && wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2256 if (!count_packed_elements (field->type,
2257 tmp.len - tmp.length_prefix_len,
2258 tmp.data + tmp.length_prefix_len,
2261 UNPACK_ERROR (("counting packed elements"));
2262 goto error_cleanup_during_scan;
2274 /* allocate space for repeated fields, also check that all required fields have been set */
2275 for (f = 0; f < desc->n_fields; f++)
2277 const ProtobufCFieldDescriptor *field = desc->fields + f;
2278 if (field->label == PROTOBUF_C_LABEL_REPEATED)
2280 size_t siz = sizeof_elt_in_repeated_array (field->type);
2281 size_t *n_ptr = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
2284 unsigned n = *n_ptr;
2286 assert(rv->descriptor != NULL);
2287 #define CLEAR_REMAINING_N_PTRS() \
2288 for(f++;f < desc->n_fields; f++) \
2290 field = desc->fields + f; \
2291 if (field->label == PROTOBUF_C_LABEL_REPEATED) \
2292 STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
2294 DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset),
2296 CLEAR_REMAINING_N_PTRS (); goto error_cleanup);
2297 #undef CLEAR_REMAINING_N_PTRS
2300 else if (field->label == PROTOBUF_C_LABEL_REQUIRED)
2302 if (field->default_value == NULL && 0 == (required_fields_bitmap[f / word_bits] & (1UL << (f % word_bits))))
2304 UNPACK_ERROR (("message '%s': missing required field '%s'", desc->name, field->name));
2310 /* allocate space for unknown fields */
2313 DO_ALLOC (rv->unknown_fields,
2314 allocator, n_unknown * sizeof (ProtobufCMessageUnknownField),
2315 goto error_cleanup);
2318 /* do real parsing */
2319 for (i_slab = 0; i_slab <= which_slab; i_slab++)
2321 unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
2322 ScannedMember *slab = scanned_member_slabs[i_slab];
2324 for (j = 0; j < max; j++)
2326 if (!parse_member (slab + j, rv, allocator))
2328 UNPACK_ERROR (("error parsing member %s of %s",
2329 slab->field ? slab->field->name : "*unknown-field*", desc->name));
2336 if (allocator->tmp_alloc == NULL)
2339 for (j = 1; j <= which_slab; j++)
2340 FREE (allocator, scanned_member_slabs[j]);
2346 protobuf_c_message_free_unpacked (rv, allocator);
2347 if (allocator->tmp_alloc == NULL)
2350 for (j = 1; j <= which_slab; j++)
2351 FREE (allocator, scanned_member_slabs[j]);
2355 error_cleanup_during_scan:
2356 FREE (allocator, rv);
2357 if (allocator->tmp_alloc == NULL)
2360 for (j = 1; j <= which_slab; j++)
2361 FREE (allocator, scanned_member_slabs[j]);
2366 /* === free_unpacked === */
2368 protobuf_c_message_free_unpacked (ProtobufCMessage *message,
2369 ProtobufCAllocator *allocator)
2371 const ProtobufCMessageDescriptor *desc = message->descriptor;
2373 ASSERT_IS_MESSAGE (message);
2374 if (allocator == NULL)
2375 allocator = &protobuf_c_default_allocator;
2376 message->descriptor = NULL;
2377 for (f = 0; f < desc->n_fields; f++)
2379 if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
2381 size_t n = STRUCT_MEMBER (size_t, message, desc->fields[f].quantifier_offset);
2382 void * arr = STRUCT_MEMBER (void *, message, desc->fields[f].offset);
2383 if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
2386 for (i = 0; i < n; i++)
2387 FREE (allocator, ((char**)arr)[i]);
2389 else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
2392 for (i = 0; i < n; i++)
2393 FREE (allocator, ((ProtobufCBinaryData*)arr)[i].data);
2395 else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
2398 for (i = 0; i < n; i++)
2399 protobuf_c_message_free_unpacked (((ProtobufCMessage**)arr)[i], allocator);
2402 FREE (allocator, arr);
2404 else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
2406 char *str = STRUCT_MEMBER (char *, message, desc->fields[f].offset);
2407 if (str && str != desc->fields[f].default_value)
2408 FREE (allocator, str);
2410 else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
2412 void *data = STRUCT_MEMBER (ProtobufCBinaryData, message, desc->fields[f].offset).data;
2413 const ProtobufCBinaryData *default_bd;
2414 default_bd = desc->fields[f].default_value;
2416 && (default_bd == NULL || default_bd->data != data))
2417 FREE (allocator, data);
2419 else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
2421 ProtobufCMessage *sm;
2422 sm = STRUCT_MEMBER (ProtobufCMessage *, message,desc->fields[f].offset);
2423 if (sm && sm != desc->fields[f].default_value)
2424 protobuf_c_message_free_unpacked (sm, allocator);
2428 for (f = 0; f < message->n_unknown_fields; f++)
2429 FREE (allocator, message->unknown_fields[f].data);
2430 if (message->unknown_fields != NULL)
2431 FREE (allocator, message->unknown_fields);
2433 FREE (allocator, message);
2436 /* === services === */
2437 typedef void (*GenericHandler)(void *service,
2438 const ProtobufCMessage *input,
2439 ProtobufCClosure closure,
2440 void *closure_data);
2442 protobuf_c_service_invoke_internal(ProtobufCService *service,
2443 unsigned method_index,
2444 const ProtobufCMessage *input,
2445 ProtobufCClosure closure,
2448 GenericHandler *handlers;
2449 GenericHandler handler;
2451 /* Verify that method_index is within range.
2452 If this fails, you are likely invoking a newly added
2453 method on an old service. (Although other memory corruption
2454 bugs can cause this assertion too) */
2455 PROTOBUF_C_ASSERT (method_index < service->descriptor->n_methods);
2457 /* Get the array of virtual methods (which are enumerated by
2458 the generated code) */
2459 handlers = (GenericHandler *) (service + 1);
2461 /* get our method and invoke it */
2462 /* TODO: seems like handler==NULL is a situation that
2464 handler = handlers[method_index];
2465 (*handler) (service, input, closure, closure_data);
2469 protobuf_c_service_generated_init (ProtobufCService *service,
2470 const ProtobufCServiceDescriptor *descriptor,
2471 ProtobufCServiceDestroy destroy)
2473 ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
2474 service->descriptor = descriptor;
2475 service->destroy = destroy;
2476 service->invoke = protobuf_c_service_invoke_internal;
2477 memset (service + 1, 0, descriptor->n_methods * sizeof (GenericHandler));
2480 void protobuf_c_service_destroy (ProtobufCService *service)
2482 service->destroy (service);
2485 /* --- querying the descriptors --- */
2486 const ProtobufCEnumValue *
2487 protobuf_c_enum_descriptor_get_value_by_name
2488 (const ProtobufCEnumDescriptor *desc,
2491 unsigned start = 0, count = desc->n_value_names;
2494 unsigned mid = start + count / 2;
2495 int rv = strcmp (desc->values_by_name[mid].name, name);
2497 return desc->values + desc->values_by_name[mid].index;
2500 count = start + count - (mid + 1);
2504 count = mid - start;
2508 if (strcmp (desc->values_by_name[start].name, name) == 0)
2509 return desc->values + desc->values_by_name[start].index;
2512 const ProtobufCEnumValue *
2513 protobuf_c_enum_descriptor_get_value
2514 (const ProtobufCEnumDescriptor *desc,
2517 int rv = int_range_lookup (desc->n_value_ranges, desc->value_ranges, value);
2520 return desc->values + rv;
2523 const ProtobufCFieldDescriptor *
2524 protobuf_c_message_descriptor_get_field_by_name
2525 (const ProtobufCMessageDescriptor *desc,
2528 unsigned start = 0, count = desc->n_fields;
2529 const ProtobufCFieldDescriptor *field;
2532 unsigned mid = start + count / 2;
2534 field = desc->fields + desc->fields_sorted_by_name[mid];
2535 rv = strcmp (field->name, name);
2540 count = start + count - (mid + 1);
2544 count = mid - start;
2548 field = desc->fields + desc->fields_sorted_by_name[start];
2549 if (strcmp (field->name, name) == 0)
2554 const ProtobufCFieldDescriptor *
2555 protobuf_c_message_descriptor_get_field
2556 (const ProtobufCMessageDescriptor *desc,
2559 int rv = int_range_lookup (desc->n_field_ranges,
2564 return desc->fields + rv;
2567 const ProtobufCMethodDescriptor *
2568 protobuf_c_service_descriptor_get_method_by_name
2569 (const ProtobufCServiceDescriptor *desc,
2572 unsigned start = 0, count = desc->n_methods;
2575 unsigned mid = start + count / 2;
2576 unsigned mid_index = desc->method_indices_by_name[mid];
2577 const char *mid_name = desc->methods[mid_index].name;
2578 int rv = strcmp (mid_name, name);
2580 return desc->methods + desc->method_indices_by_name[mid];
2583 count = start + count - (mid + 1);
2588 count = mid - start;
2593 if (strcmp (desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
2594 return desc->methods + desc->method_indices_by_name[start];