4e4094f78b8c961b06cc51d65ceff2befdbc14f8
[umurmur.git] / src / google / protobuf-c / protobuf-c.c
1 /* --- protobuf-c.c: public protobuf c runtime implementation --- */
2
3 /*
4  * Copyright 2008, Dave Benson.
5  * 
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
15  * under the License.
16  */
17
18 /* TODO items:
19
20      * 64-BIT OPTIMIZATION: certain implementations use 32-bit math even on 64-bit platforms
21         (uint64_size, uint64_pack, parse_uint64)
22
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)
29
30      * use TRUE and FALSE instead of 1 and 0 as appropriate
31
32      * use size_t consistently
33  */
34
35 #include <stdio.h>                      /* for occasional printf()s */
36 #include <stdlib.h>                     /* for abort(), malloc() etc */
37 #include <string.h>                     /* for strlen(), memcpy(), memmove() */
38
39 #ifndef PRINT_UNPACK_ERRORS
40 #define PRINT_UNPACK_ERRORS              1
41 #endif
42
43 #include "protobuf-c.h"
44
45 #define MAX_UINT64_ENCODED_SIZE 10
46
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)))
58 #define TRUE 1
59 #define FALSE 0
60
61 static void
62 alloc_failed_warning (unsigned size, const char *filename, unsigned line)
63 {
64   fprintf (stderr,
65            "WARNING: out-of-memory allocating a block of size %u (%s:%u)\n",
66            size, filename, line);
67 }
68
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)                                             \
73     dst = NULL;                                                             \
74   else if ((dst=((allocator)->alloc ((allocator)->allocator_data,           \
75                                      da__allocation_size))) == NULL)        \
76     {                                                                       \
77       alloc_failed_warning (da__allocation_size, __FILE__, __LINE__);       \
78       fail_code;                                                            \
79     }                                                                       \
80 }
81 #define DO_UNALIGNED_ALLOC  DO_ALLOC            /* placeholder */
82
83
84
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)
93
94 /* --- allocator --- */
95
96 static void protobuf_c_out_of_memory_default (void)
97 {
98   fprintf (stderr, "Out Of Memory!!!\n");
99   abort ();
100 }
101 void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
102
103 static void *system_alloc(void *allocator_data, size_t size)
104 {
105   void *rv;
106   (void) allocator_data;
107   if (size == 0)
108     return NULL;
109   rv = malloc (size);
110   if (rv == NULL)
111     protobuf_c_out_of_memory ();
112   return rv;
113 }
114
115 static void system_free (void *allocator_data, void *data)
116 {
117   (void) allocator_data;
118   if (data)
119     free (data);
120 }
121
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 =
126 {
127   system_alloc,
128   system_free,
129   NULL,
130   8192,
131   NULL
132 };
133
134 /* Users should NOT modify this structure,
135    but it's difficult to prevent.
136
137    please modify protobuf_c_default_allocator instead. */
138 ProtobufCAllocator protobuf_c_system_allocator =
139 {
140   system_alloc,
141   system_free,
142   NULL,
143   8192,
144   NULL
145 };
146
147 /* === buffer-simple === */
148 void
149 protobuf_c_buffer_simple_append (ProtobufCBuffer *buffer,
150                                  size_t           len,
151                                  const uint8_t   *data)
152 {
153   ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
154   size_t new_len = simp->len + len;
155   if (new_len > simp->alloced)
156     {
157       size_t new_alloced = simp->alloced * 2;
158       uint8_t *new_data;
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);
165       else
166         simp->must_free_data = 1;
167       simp->data = new_data;
168       simp->alloced = new_alloced;
169     }
170   memcpy (simp->data + simp->len, data, len);
171   simp->len = new_len;
172 }
173
174 /* === get_packed_size() === */
175
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. */
179 static inline size_t
180 get_tag_size (unsigned number)
181 {
182   if (number < (1<<4))
183     return 1;
184   else if (number < (1<<11))
185     return 2;
186   else if (number < (1<<18))
187     return 3;
188   else if (number < (1<<25))
189     return 4;
190   else
191     return 5;
192 }
193
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. */
197 static inline size_t
198 uint32_size (uint32_t v)
199 {
200   if (v < (1<<7))
201     return 1;
202   else if (v < (1<<14))
203     return 2;
204   else if (v < (1<<21))
205     return 3;
206   else if (v < (1<<28))
207     return 4;
208   else
209     return 5;
210 }
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. */
214 static inline size_t
215 int32_size (int32_t v)
216 {
217   if (v < 0)
218     return 10;
219   else if (v < (1<<7))
220     return 1;
221   else if (v < (1<<14))
222     return 2;
223   else if (v < (1<<21))
224     return 3;
225   else if (v < (1<<28))
226     return 4;
227   else
228     return 5;
229 }
230 /* return the zigzag-encoded 32-bit unsigned int from a 32-bit signed int */
231 static inline uint32_t
232 zigzag32 (int32_t v)
233 {
234   if (v < 0)
235     return ((uint32_t)(-v)) * 2 - 1;
236   else
237     return v * 2;
238 }
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. */
243 static inline size_t
244 sint32_size (int32_t v)
245 {
246   return uint32_size(zigzag32(v));
247 }
248
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. */
252 static inline size_t
253 uint64_size (uint64_t v)
254 {
255   uint32_t upper_v = (v>>32);
256   if (upper_v == 0)
257     return uint32_size ((uint32_t)v);
258   else if (upper_v < (1<<3))
259     return 5;
260   else if (upper_v < (1<<10))
261     return 6;
262   else if (upper_v < (1<<17))
263     return 7;
264   else if (upper_v < (1<<24))
265     return 8;
266   else if (upper_v < (1U<<31))
267     return 9;
268   else
269     return 10;
270 }
271
272 /* return the zigzag-encoded 64-bit unsigned int from a 64-bit signed int */
273 static inline uint64_t
274 zigzag64 (int64_t v)
275 {
276   if (v < 0)
277     return ((uint64_t)(-v)) * 2 - 1;
278   else
279     return v * 2;
280 }
281
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. */
286 static inline size_t
287 sint64_size (int64_t v)
288 {
289   return uint64_size(zigzag64(v));
290 }
291
292 /* Get serialized size of a single field in the message,
293    including the space needed by the identifying tag. */
294 static size_t
295 required_field_get_packed_size (const ProtobufCFieldDescriptor *field,
296                                 const void *member)
297 {
298   size_t rv = get_tag_size (field->id);
299   switch (field->type)
300     {
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:
314       return rv + 4;
315     case PROTOBUF_C_TYPE_SFIXED64:
316     case PROTOBUF_C_TYPE_FIXED64:
317       return rv + 8;
318     case PROTOBUF_C_TYPE_BOOL:
319       return rv + 1;
320     case PROTOBUF_C_TYPE_FLOAT:
321       return rv + 4;
322     case PROTOBUF_C_TYPE_DOUBLE:
323       return rv + 8;
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:
328       {
329         const char *str = *(char * const *) member;
330         size_t len = str ? strlen (str) : 0;
331         return rv + uint32_size (len) + len;
332       }
333     case PROTOBUF_C_TYPE_BYTES:
334       {
335         size_t len = ((const ProtobufCBinaryData*) member)->len;
336         return rv + uint32_size (len) + len;
337       }
338     //case PROTOBUF_C_TYPE_GROUP:
339     case PROTOBUF_C_TYPE_MESSAGE:
340       {
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;
344       }
345     }
346   PROTOBUF_C_ASSERT_NOT_REACHED ();
347   return 0;
348 }
349
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. */
353 static size_t
354 optional_field_get_packed_size (const ProtobufCFieldDescriptor *field,
355                                 const protobuf_c_boolean *has,
356                                 const void *member)
357 {
358   if (field->type == PROTOBUF_C_TYPE_MESSAGE
359    || field->type == PROTOBUF_C_TYPE_STRING)
360     {
361       const void *ptr = * (const void * const *) member;
362       if (ptr == NULL
363        || ptr == field->default_value)
364         return 0;
365     }
366   else
367     {
368       if (!*has)
369         return 0;
370     }
371   return required_field_get_packed_size (field, member);
372 }
373
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). */
377 static size_t
378 repeated_field_get_packed_size (const ProtobufCFieldDescriptor *field,
379                                 size_t count,
380                                 const void *member)
381 {
382   size_t header_size;
383   size_t rv = 0;
384   unsigned i;
385   void *array = * (void * const *) member;
386   if (count == 0)
387     return 0;
388   header_size = get_tag_size (field->id);
389   if (!field->packed)
390     header_size *= count;
391   switch (field->type)
392     {
393     case PROTOBUF_C_TYPE_SINT32:
394       for (i = 0; i < count; i++)
395         rv += sint32_size (((int32_t*)array)[i]);
396       break;
397     case PROTOBUF_C_TYPE_INT32:
398       for (i = 0; i < count; i++)
399         rv += int32_size (((uint32_t*)array)[i]);
400       break;
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]);
405       break;
406     case PROTOBUF_C_TYPE_SINT64:
407       for (i = 0; i < count; i++)
408         rv += sint64_size (((int64_t*)array)[i]);
409       break;
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]);
414       break;
415     case PROTOBUF_C_TYPE_SFIXED32:
416     case PROTOBUF_C_TYPE_FIXED32:
417     case PROTOBUF_C_TYPE_FLOAT:
418       rv += 4 * count;
419       break;
420     case PROTOBUF_C_TYPE_SFIXED64:
421     case PROTOBUF_C_TYPE_FIXED64:
422     case PROTOBUF_C_TYPE_DOUBLE:
423       rv += 8 * count;
424       break;
425     case PROTOBUF_C_TYPE_BOOL:
426       rv += count;
427       break;
428     case PROTOBUF_C_TYPE_STRING:
429       for (i = 0; i < count; i++)
430         {
431           size_t len = strlen (((char**) array)[i]);
432           rv += uint32_size (len) + len;
433         }
434       break;
435       
436     case PROTOBUF_C_TYPE_BYTES:
437       for (i = 0; i < count; i++)
438         {
439           size_t len = ((ProtobufCBinaryData*) array)[i].len;
440           rv += uint32_size (len) + len;
441         }
442       break;
443     case PROTOBUF_C_TYPE_MESSAGE:
444       for (i = 0; i < count; i++)
445         {
446           size_t len = protobuf_c_message_get_packed_size (((ProtobufCMessage **) array)[i]);
447           rv += uint32_size (len) + len;
448         }
449       break;
450     //case PROTOBUF_C_TYPE_GROUP:          // NOT SUPPORTED
451     }
452   if (field->packed)
453     header_size += uint32_size (rv);
454   return header_size + rv;
455 }
456
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). */
460 static inline size_t
461 unknown_field_get_packed_size (const ProtobufCMessageUnknownField *field)
462 {
463   return get_tag_size (field->tag) + field->len;
464 }
465
466 /* Get the number of bytes that the message will occupy once serialized. */
467 size_t
468 protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
469 {
470   unsigned i;
471   size_t rv = 0;
472   ASSERT_IS_MESSAGE (message);
473   for (i = 0; i < message->descriptor->n_fields; i++)
474     {
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;
478
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);
483       else 
484         rv += repeated_field_get_packed_size (field, * (const size_t *) qmember, member);
485     }
486   for (i = 0; i < message->n_unknown_fields; i++)
487     rv += unknown_field_get_packed_size (&message->unknown_fields[i]);
488   return rv;
489 }
490 /* === pack() === */
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. */
493 static inline size_t
494 uint32_pack (uint32_t value, uint8_t *out)
495 {
496   unsigned rv = 0;
497   if (value >= 0x80)
498     {
499       out[rv++] = value | 0x80;
500       value >>= 7;
501       if (value >= 0x80)
502         {
503           out[rv++] = value | 0x80;
504           value >>= 7;
505           if (value >= 0x80)
506             {
507               out[rv++] = value | 0x80;
508               value >>= 7;
509               if (value >= 0x80)
510                 {
511                   out[rv++] = value | 0x80;
512                   value >>= 7;
513                 }
514             }
515         }
516     }
517   /* assert: value<128 */
518   out[rv++] = value;
519   return rv;
520 }
521
522 /* Pack a 32-bit signed integer, returning the number of bytes needed.
523    Negative numbers are packed as twos-complement 64-bit integers. */
524 static inline size_t
525 int32_pack (int32_t value, uint8_t *out)
526 {
527   if (value < 0)
528     {
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;
535       out[9] = 0x01;
536       return 10;
537     }
538   else
539     return uint32_pack (value, out);
540 }
541
542 /* Pack a 32-bit integer in zigwag encoding. */
543 static inline size_t
544 sint32_pack (int32_t value, uint8_t *out)
545 {
546   return uint32_pack (zigzag32 (value), out);
547 }
548
549 /* Pack a 64-bit unsigned integer that fits in a 64-bit uint,
550    using base-128 encoding. */
551 static size_t
552 uint64_pack (uint64_t value, uint8_t *out)
553 {
554   uint32_t hi = value>>32;
555   uint32_t lo = value;
556   unsigned rv;
557   if (hi == 0)
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;
563   if (hi < 8)
564     {
565       out[4] = (hi<<4) | (lo>>28);
566       return 5;
567     }
568   else
569     {
570       out[4] = ((hi&7)<<4) | (lo>>28) | 0x80;
571       hi >>= 3;
572     }
573   rv = 5;
574   while (hi >= 128)
575     {
576       out[rv++] = hi | 0x80;
577       hi >>= 7;
578     }
579   out[rv++] = hi;
580   return rv;
581 }
582
583 /* Pack a 64-bit signed integer in zigzan encoding,
584    return the size of the packed output.
585    (Max returned value is 10) */
586 static inline size_t
587 sint64_pack (int64_t value, uint8_t *out)
588 {
589   return uint64_pack (zigzag64 (value), out);
590 }
591
592 /* Pack a 32-bit value, little-endian.
593    Used for fixed32, sfixed32, float) */
594 static inline size_t
595 fixed32_pack (uint32_t value, uint8_t *out)
596 {
597 #if IS_LITTLE_ENDIAN
598   memcpy (out, &value, 4);
599 #else
600   out[0] = value;
601   out[1] = value>>8;
602   out[2] = value>>16;
603   out[3] = value>>24;
604 #endif
605   return 4;
606 }
607
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. */
613 static inline size_t
614 fixed64_pack (uint64_t value, uint8_t *out)
615 {
616 #if IS_LITTLE_ENDIAN
617   memcpy (out, &value, 8);
618 #else
619   fixed32_pack (value, out);
620   fixed32_pack (value>>32, out+4);
621 #endif
622   return 8;
623 }
624
625
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. */
630 static inline size_t
631 boolean_pack (protobuf_c_boolean value, uint8_t *out)
632 {
633   *out = value ? 1 : 0;
634   return 1;
635 }
636
637 /* Pack a length-prefixed string.
638    The input string is NUL-terminated.
639
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).
645  */
646 static inline size_t
647 string_pack (const char * str, uint8_t *out)
648 {
649   if (str == NULL)
650     {
651       out[0] = 0;
652       return 1;
653     }
654   else
655     {
656       size_t len = strlen (str);
657       size_t rv = uint32_pack (len, out);
658       memcpy (out + rv, str, len);
659       return rv + len;
660     }
661 }
662
663 static inline size_t
664 binary_data_pack (const ProtobufCBinaryData *bd, uint8_t *out)
665 {
666   size_t len = bd->len;
667   size_t rv = uint32_pack (len, out);
668   memcpy (out + rv, bd->data, len);
669   return rv + len;
670 }
671
672 static inline size_t
673 prefixed_message_pack (const ProtobufCMessage *message, uint8_t *out)
674 {
675   if (message == NULL)
676     {
677       out[0] = 0;
678       return 1;
679     }
680   else
681     {
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;
687     }
688 }
689
690 /* wire-type will be added in required_field_pack() */
691 /* XXX: just call uint64_pack on 64-bit platforms. */
692 static size_t
693 tag_pack (uint32_t id, uint8_t *out)
694 {
695   if (id < (1<<(32-3)))
696     return uint32_pack (id<<3, out);
697   else
698     return uint64_pack (((uint64_t)id) << 3, out);
699 }
700
701 static size_t
702 required_field_pack (const ProtobufCFieldDescriptor *field,
703                      const void *member,
704                      uint8_t *out)
705 {
706   size_t rv = tag_pack (field->id, out);
707   switch (field->type)
708     {
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:
740       {
741         out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
742         return rv + string_pack (*(char * const *) member, out + rv);
743       }
744       
745     case PROTOBUF_C_TYPE_BYTES:
746       {
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);
750       }
751     //case PROTOBUF_C_TYPE_GROUP:          // NOT SUPPORTED
752     case PROTOBUF_C_TYPE_MESSAGE:
753       {
754         out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
755         return rv + prefixed_message_pack (*(ProtobufCMessage * const *) member,
756                                            out + rv);
757       }
758     }
759   PROTOBUF_C_ASSERT_NOT_REACHED ();
760   return 0;
761 }
762 static size_t
763 optional_field_pack (const ProtobufCFieldDescriptor *field,
764                      const protobuf_c_boolean *has,
765                      const void *member,
766                      uint8_t *out)
767 {
768   if (field->type == PROTOBUF_C_TYPE_MESSAGE
769    || field->type == PROTOBUF_C_TYPE_STRING)
770     {
771       const void *ptr = * (const void * const *) member;
772       if (ptr == NULL
773        || ptr == field->default_value)
774         return 0;
775     }
776   else
777     {
778       if (!*has)
779         return 0;
780     }
781   return required_field_pack (field, member, out);
782 }
783
784 /* TODO: implement as a table lookup */
785 static inline size_t
786 sizeof_elt_in_repeated_array (ProtobufCType type)
787 {
788   switch (type)
789     {
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:
797       return 4;
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:
804       return 8;
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);
812     }
813   PROTOBUF_C_ASSERT_NOT_REACHED ();
814   return 0;
815 }
816
817 static void
818 copy_to_little_endian_32 (void *out, const void *in, unsigned N)
819 {
820 #if IS_LITTLE_ENDIAN
821   memcpy (out, in, N * 4);
822 #else
823   unsigned i;
824   const uint32_t *ini = in;
825   for (i = 0; i < N; i++)
826     fixed32_pack (ini[i], (uint32_t*)out + i);
827 #endif
828 }
829 static void
830 copy_to_little_endian_64 (void *out, const void *in, unsigned N)
831 {
832 #if IS_LITTLE_ENDIAN
833   memcpy (out, in, N * 8);
834 #else
835   unsigned i;
836   const uint64_t *ini = in;
837   for (i = 0; i < N; i++)
838     fixed64_pack (ini[i], (uint64_t*)out + i);
839 #endif
840 }
841
842 static unsigned
843 get_type_min_size (ProtobufCType type)
844 {
845   if (type == PROTOBUF_C_TYPE_SFIXED32
846    || type == PROTOBUF_C_TYPE_FIXED32
847    || type == PROTOBUF_C_TYPE_FLOAT)
848     return 4;
849   if (type == PROTOBUF_C_TYPE_SFIXED64
850    || type == PROTOBUF_C_TYPE_FIXED64
851    || type == PROTOBUF_C_TYPE_DOUBLE)
852     return 8;
853   return 1;
854 }
855
856 static size_t
857 repeated_field_pack (const ProtobufCFieldDescriptor *field,
858                      size_t count,
859                      const void *member,
860                      uint8_t *out)
861 {
862   char *array = * (char * const *) member;
863   unsigned i;
864   if (field->packed)
865     {
866       unsigned header_len;
867       unsigned len_start;
868       unsigned min_length;
869       unsigned payload_len;
870       unsigned length_size_min;
871       unsigned actual_length_size;
872       uint8_t *payload_at;
873       if (count == 0)
874         return 0;
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;
882       switch (field->type)
883         {
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;
889           break;
890
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;
896           break;
897
898         case PROTOBUF_C_TYPE_INT32:
899           {
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);
903           }
904           break;
905
906         case PROTOBUF_C_TYPE_SINT32:
907           {
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);
911           }
912           break;
913
914         case PROTOBUF_C_TYPE_SINT64:
915           {
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);
919           }
920           break;
921         case PROTOBUF_C_TYPE_ENUM:
922         case PROTOBUF_C_TYPE_UINT32:
923           {
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);
927           }
928           break;
929         case PROTOBUF_C_TYPE_INT64:
930         case PROTOBUF_C_TYPE_UINT64:
931           {
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);
935           }
936           break;
937         case PROTOBUF_C_TYPE_BOOL:
938           {
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);
942           }
943           break;
944           
945         default:
946           assert (0);
947         }
948       payload_len = payload_at - (out + header_len);
949       actual_length_size = uint32_size (payload_len);
950       if (length_size_min != actual_length_size)
951         {
952           assert (actual_length_size == length_size_min + 1);
953           memmove (out + header_len + 1, out + header_len, payload_len);
954           header_len++;
955         }
956       uint32_pack (payload_len, out + len_start);
957       return header_len + payload_len;
958     }
959   else
960     {
961       /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
962       size_t rv = 0;
963       unsigned siz = sizeof_elt_in_repeated_array (field->type);
964       for (i = 0; i < count; i++)
965         {
966           rv += required_field_pack (field, array, out + rv);
967           array += siz;
968         }
969       return rv;
970     }
971 }
972 static size_t
973 unknown_field_pack (const ProtobufCMessageUnknownField *field,
974                     uint8_t *out)
975 {
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;
980 }
981
982 size_t
983 protobuf_c_message_pack           (const ProtobufCMessage *message,
984                                    uint8_t                *out)
985 {
986   unsigned i;
987   size_t rv = 0;
988   ASSERT_IS_MESSAGE (message);
989   for (i = 0; i < message->descriptor->n_fields; i++)
990     {
991       const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
992       const void *member = ((const char *) message) + field->offset;
993
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
996          the field is one of:
997            - a repeated field
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;
1001
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);
1008       else
1009         rv += repeated_field_pack (field, * (const size_t *) qmember, member, out + rv);
1010     }
1011   for (i = 0; i < message->n_unknown_fields; i++)
1012     rv += unknown_field_pack (&message->unknown_fields[i], out + rv);
1013   return rv;
1014 }
1015
1016 /* === pack_to_buffer() === */
1017 static size_t
1018 required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1019                                const void *member,
1020                                ProtobufCBuffer *buffer)
1021 {
1022   size_t rv;
1023   uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1024   rv = tag_pack (field->id, scratch);
1025   switch (field->type)
1026     {
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);
1031       break;
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);
1036       break;
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);
1042       break;
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);
1047       break;
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);
1053       break;
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);
1060       break;
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);
1067       break;
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);
1072       break;
1073     case PROTOBUF_C_TYPE_STRING:
1074       {
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);
1081         rv += sublen;
1082         break;
1083       }
1084       
1085     case PROTOBUF_C_TYPE_BYTES:
1086       {
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);
1093         rv += sublen;
1094         break;
1095       }
1096     //PROTOBUF_C_TYPE_GROUP,          // NOT SUPPORTED
1097     case PROTOBUF_C_TYPE_MESSAGE:
1098       {
1099         uint8_t simple_buffer_scratch[256];
1100         size_t sublen;
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;
1105         if (msg == NULL)
1106           sublen = 0;
1107         else
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);
1112         rv += sublen;
1113         PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&simple_buffer);
1114         break;
1115       }
1116     default:
1117       PROTOBUF_C_ASSERT_NOT_REACHED ();
1118     }
1119   return rv;
1120 }
1121 static size_t
1122 optional_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1123                                const protobuf_c_boolean *has,
1124                                const void *member,
1125                                ProtobufCBuffer *buffer)
1126 {
1127   if (field->type == PROTOBUF_C_TYPE_MESSAGE
1128    || field->type == PROTOBUF_C_TYPE_STRING)
1129     {
1130       const void *ptr = * (const void * const *) member;
1131       if (ptr == NULL
1132        || ptr == field->default_value)
1133         return 0;
1134     }
1135   else
1136     {
1137       if (!*has)
1138         return 0;
1139     }
1140   return required_field_pack_to_buffer (field, member, buffer);
1141 }
1142
1143 static size_t
1144 get_packed_payload_length (const ProtobufCFieldDescriptor *field,
1145                            unsigned count,
1146                            const void *array)
1147 {
1148   unsigned rv = 0;
1149   unsigned i;
1150   switch (field->type)
1151     {
1152     case PROTOBUF_C_TYPE_SFIXED32:
1153     case PROTOBUF_C_TYPE_FIXED32:
1154     case PROTOBUF_C_TYPE_FLOAT:
1155       return count * 4;
1156
1157     case PROTOBUF_C_TYPE_SFIXED64:
1158     case PROTOBUF_C_TYPE_FIXED64:
1159     case PROTOBUF_C_TYPE_DOUBLE:
1160       return count * 8;
1161
1162     case PROTOBUF_C_TYPE_INT32:
1163       {
1164         const int32_t *arr = (const int32_t *) array;
1165         for (i = 0; i < count; i++)
1166           rv += int32_size (arr[i]);
1167       }
1168       break;
1169
1170     case PROTOBUF_C_TYPE_SINT32:
1171       {
1172         const int32_t *arr = (const int32_t *) array;
1173         for (i = 0; i < count; i++)
1174           rv += sint32_size (arr[i]);
1175       }
1176       break;
1177     case PROTOBUF_C_TYPE_ENUM:
1178     case PROTOBUF_C_TYPE_UINT32:
1179       {
1180         const uint32_t *arr = (const uint32_t *) array;
1181         for (i = 0; i < count; i++)
1182           rv += uint32_size (arr[i]);
1183       }
1184       break;
1185
1186     case PROTOBUF_C_TYPE_SINT64:
1187       {
1188         const int64_t *arr = (const int64_t *) array;
1189         for (i = 0; i < count; i++)
1190           rv += sint64_size (arr[i]);
1191       }
1192       break;
1193     case PROTOBUF_C_TYPE_INT64:
1194     case PROTOBUF_C_TYPE_UINT64:
1195       {
1196         const uint64_t *arr = (const uint64_t *) array;
1197         for (i = 0; i < count; i++)
1198           rv += uint64_size (arr[i]);
1199       }
1200       break;
1201     case PROTOBUF_C_TYPE_BOOL:
1202       return count;
1203     default:
1204       assert (0);
1205     }
1206   return rv;
1207 }
1208 static size_t
1209 pack_buffer_packed_payload (const ProtobufCFieldDescriptor *field,
1210                             unsigned count,
1211                             const void *array,
1212                             ProtobufCBuffer *buffer)
1213 {
1214   uint8_t scratch[16];
1215   size_t rv = 0;
1216   unsigned i;
1217   switch (field->type)
1218     {
1219       case PROTOBUF_C_TYPE_SFIXED32:
1220       case PROTOBUF_C_TYPE_FIXED32:
1221       case PROTOBUF_C_TYPE_FLOAT:
1222 #if IS_LITTLE_ENDIAN
1223         rv = count * 4;
1224         goto no_packing_needed;
1225 #else
1226         for (i = 0; i < count; i++)
1227           {
1228             unsigned len = fixed32_pack (((uint32_t*)array)[i], scratch);
1229             buffer->append (buffer, len, scratch);
1230             rv += len;
1231           }
1232 #endif
1233         break;
1234       case PROTOBUF_C_TYPE_SFIXED64:
1235       case PROTOBUF_C_TYPE_FIXED64:
1236       case PROTOBUF_C_TYPE_DOUBLE:
1237 #if IS_LITTLE_ENDIAN
1238         rv = count * 8;
1239         goto no_packing_needed;
1240 #else
1241         for (i = 0; i < count; i++)
1242           {
1243             unsigned len = fixed64_pack (((uint64_t*)array)[i], scratch);
1244             buffer->append (buffer, len, scratch);
1245             rv += len;
1246           }
1247         break;
1248 #endif
1249       case PROTOBUF_C_TYPE_INT32:
1250         for (i = 0; i < count; i++)
1251           {
1252             unsigned len = int32_pack (((int32_t*)array)[i], scratch);
1253             buffer->append (buffer, len, scratch);
1254             rv += len;
1255           }
1256         break;
1257
1258       case PROTOBUF_C_TYPE_SINT32:
1259         for (i = 0; i < count; i++)
1260           {
1261             unsigned len = sint32_pack (((int32_t*)array)[i], scratch);
1262             buffer->append (buffer, len, scratch);
1263             rv += len;
1264           }
1265         break;
1266       case PROTOBUF_C_TYPE_ENUM:
1267       case PROTOBUF_C_TYPE_UINT32:
1268         for (i = 0; i < count; i++)
1269           {
1270             unsigned len = uint32_pack (((uint32_t*)array)[i], scratch);
1271             buffer->append (buffer, len, scratch);
1272             rv += len;
1273           }
1274         break;
1275
1276       case PROTOBUF_C_TYPE_SINT64:
1277         for (i = 0; i < count; i++)
1278           {
1279             unsigned len = sint64_pack (((int64_t*)array)[i], scratch);
1280             buffer->append (buffer, len, scratch);
1281             rv += len;
1282           }
1283         break;
1284       case PROTOBUF_C_TYPE_INT64:
1285       case PROTOBUF_C_TYPE_UINT64:
1286         for (i = 0; i < count; i++)
1287           {
1288             unsigned len = uint64_pack (((uint64_t*)array)[i], scratch);
1289             buffer->append (buffer, len, scratch);
1290             rv += len;
1291           }
1292         break;
1293       case PROTOBUF_C_TYPE_BOOL:
1294         for (i = 0; i < count; i++)
1295           {
1296             unsigned len = boolean_pack (((protobuf_c_boolean*)array)[i], scratch);
1297             buffer->append (buffer, len, scratch);
1298             rv += len;
1299           }
1300         return count;
1301       default:
1302         assert(0);
1303     }
1304   return rv;
1305
1306 no_packing_needed:
1307   buffer->append (buffer, rv, array);
1308   return rv;
1309 }
1310
1311 static size_t
1312 repeated_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
1313                                unsigned count,
1314                                const void *member,
1315                                ProtobufCBuffer *buffer)
1316 {
1317   char *array = * (char * const *) member;
1318   if (count == 0)
1319     return 0;
1320   if (field->packed)
1321     {
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);
1325       size_t tmp;
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;
1332     }
1333   else
1334     {
1335       size_t siz;
1336       unsigned i;
1337       /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1338       unsigned rv = 0;
1339       siz = sizeof_elt_in_repeated_array (field->type);
1340       for (i = 0; i < count; i++)
1341         {
1342           rv += required_field_pack_to_buffer (field, array, buffer);
1343           array += siz;
1344         }
1345       return rv;
1346     }
1347 }
1348
1349 static size_t
1350 unknown_field_pack_to_buffer (const ProtobufCMessageUnknownField *field,
1351                               ProtobufCBuffer *buffer)
1352 {
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;
1359 }
1360
1361 size_t
1362 protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
1363                                    ProtobufCBuffer  *buffer)
1364 {
1365   unsigned i;
1366   size_t rv = 0;
1367   ASSERT_IS_MESSAGE (message);
1368   for (i = 0; i < message->descriptor->n_fields; i++)
1369     {
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;
1373
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);
1378       else
1379         rv += repeated_field_pack_to_buffer (field, * (const size_t *) qmember, member, buffer);
1380     }
1381   for (i = 0; i < message->n_unknown_fields; i++)
1382     rv += unknown_field_pack_to_buffer (&message->unknown_fields[i], buffer);
1383
1384   return rv;
1385 }
1386
1387 /* === unpacking === */
1388 #if PRINT_UNPACK_ERRORS
1389 # define UNPACK_ERROR(args)  do { printf args;printf("\n"); }while(0)
1390 #else
1391 # define UNPACK_ERROR(args)  do { } while (0)
1392 #endif
1393
1394 static inline int
1395 int_range_lookup (unsigned n_ranges,
1396                   const ProtobufCIntRange *ranges,
1397                   int value)
1398 {
1399   unsigned start, n;
1400   if (n_ranges == 0)
1401     return -1;
1402   start = 0;
1403   n = n_ranges;
1404   while (n > 1)
1405     {
1406       unsigned mid = start + n / 2;
1407       if (value < ranges[mid].start_value)
1408         {
1409           n = mid - start;
1410         }
1411       else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
1412         {
1413           unsigned new_start = mid + 1;
1414           n = start + n - new_start;
1415           start = new_start;
1416         }
1417       else
1418         return (value - ranges[mid].start_value) + ranges[mid].orig_index;
1419     }
1420   if (n > 0)
1421     {
1422       unsigned start_orig_index = ranges[start].orig_index;
1423       unsigned range_size = ranges[start+1].orig_index - start_orig_index;
1424
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;
1428     }
1429   return -1;
1430 }
1431
1432 static size_t
1433 parse_tag_and_wiretype (size_t len,
1434                         const uint8_t *data,
1435                         uint32_t *tag_out,
1436                         ProtobufCWireType *wiretype_out)
1437 {
1438   unsigned max_rv = len > 5 ? 5 : len;
1439   uint32_t tag = (data[0]&0x7f) >> 3;
1440   unsigned shift = 4;
1441   unsigned rv;
1442   *wiretype_out = data[0] & 7;
1443   if ((data[0] & 0x80) == 0)
1444     {
1445       *tag_out = tag;
1446       return 1;
1447     }
1448   for (rv = 1; rv < max_rv; rv++)
1449     if (data[rv] & 0x80)
1450       {
1451         tag |= (data[rv] & 0x7f) << shift;
1452         shift += 7;
1453       }
1454     else
1455       {
1456         tag |= data[rv] << shift;
1457         *tag_out = tag;
1458         return rv + 1;
1459       }
1460   return 0;                   /* error: bad header */
1461 }
1462
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
1467 {
1468   uint32_t tag;
1469   uint8_t wire_type;
1470   uint8_t length_prefix_len;
1471   const ProtobufCFieldDescriptor *field;
1472   size_t len;
1473   const uint8_t *data;
1474 };
1475
1476 static inline uint32_t
1477 scan_length_prefixed_data (size_t len, const uint8_t *data, size_t *prefix_len_out)
1478 {
1479   unsigned hdr_max = len < 5 ? len : 5;
1480   unsigned hdr_len;
1481   uint32_t val = 0;
1482   unsigned i;
1483   unsigned shift = 0;
1484   for (i = 0; i < hdr_max; i++)
1485     {
1486       val |= (data[i] & 0x7f) << shift;
1487       shift += 7;
1488       if ((data[i] & 0x80) == 0)
1489         break;
1490     }
1491   if (i == hdr_max)
1492     {
1493       UNPACK_ERROR (("error parsing length for length-prefixed data"));
1494       return 0;
1495     }
1496   hdr_len = i + 1;
1497   *prefix_len_out = hdr_len;
1498   if (hdr_len + val > len)
1499     {
1500       UNPACK_ERROR (("data too short after length-prefix of %u",
1501                      val));
1502       return 0;
1503     }
1504   return hdr_len + val;
1505 }
1506
1507 static size_t 
1508 max_b128_numbers (size_t len, const uint8_t *data)
1509 {
1510   size_t rv = 0;
1511   while (len--)
1512     if ((*data++ & 0x80) == 0)
1513       ++rv;
1514   return rv;
1515 }
1516
1517
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,
1525                        size_t len,
1526                        const uint8_t *data,
1527                        size_t *count_out)
1528 {
1529   switch (type)
1530     {
1531     case PROTOBUF_C_TYPE_SFIXED32:
1532     case PROTOBUF_C_TYPE_FIXED32:
1533     case PROTOBUF_C_TYPE_FLOAT:
1534       if (len % 4 != 0)
1535         {
1536           UNPACK_ERROR (("length must be a multiple of 4 for fixed-length 32-bit types"));
1537           return FALSE;
1538         }
1539       *count_out = len / 4;
1540       return TRUE;
1541
1542     case PROTOBUF_C_TYPE_SFIXED64:
1543     case PROTOBUF_C_TYPE_FIXED64:
1544     case PROTOBUF_C_TYPE_DOUBLE:
1545       if (len % 8 != 0)
1546         {
1547           UNPACK_ERROR (("length must be a multiple of 8 for fixed-length 64-bit types"));
1548           return FALSE;
1549         }
1550       *count_out = len / 8;
1551       return TRUE;
1552
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);
1561       return TRUE;
1562     case PROTOBUF_C_TYPE_BOOL:
1563       *count_out = len;
1564       return TRUE;
1565
1566     case PROTOBUF_C_TYPE_STRING:
1567     case PROTOBUF_C_TYPE_BYTES:
1568     case PROTOBUF_C_TYPE_MESSAGE:
1569     default:
1570       UNPACK_ERROR (("bad protobuf-c type %u for packed-repeated", type));
1571       return FALSE;
1572     }
1573 }
1574
1575 static inline uint32_t
1576 parse_uint32 (unsigned len, const uint8_t *data)
1577 {
1578   unsigned rv = data[0] & 0x7f;
1579   if (len > 1)
1580     {
1581       rv |= ((data[1] & 0x7f) << 7);
1582       if (len > 2)
1583         {
1584           rv |= ((data[2] & 0x7f) << 14);
1585           if (len > 3)
1586             {
1587               rv |= ((data[3] & 0x7f) << 21);
1588               if (len > 4)
1589                 rv |= (data[4] << 28);
1590             }
1591         }
1592     }
1593   return rv;
1594 }
1595 static inline uint32_t
1596 parse_int32 (unsigned len, const uint8_t *data)
1597 {
1598   return parse_uint32 (len, data);
1599 }
1600 static inline int32_t
1601 unzigzag32 (uint32_t v)
1602 {
1603   if (v&1)
1604     return -(v>>1) - 1;
1605   else
1606     return v>>1;
1607 }
1608 static inline uint32_t
1609 parse_fixed_uint32 (const uint8_t *data)
1610 {
1611 #if IS_LITTLE_ENDIAN
1612   uint32_t t;
1613   memcpy (&t, data, 4);
1614   return t;
1615 #else
1616   return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
1617 #endif
1618 }
1619 static uint64_t
1620 parse_uint64 (unsigned len, const uint8_t *data)
1621 {
1622   unsigned shift, i;
1623   if (len < 5)
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);
1629   shift = 28;
1630   for (i = 4; i < len; i++)
1631     {
1632       rv |= (((uint64_t)(data[i]&0x7f)) << shift);
1633       shift += 7;
1634     }
1635   return rv;
1636 }
1637 static inline int64_t
1638 unzigzag64 (uint64_t v)
1639 {
1640   if (v&1)
1641     return -(v>>1) - 1;
1642   else
1643     return v>>1;
1644 }
1645 static inline uint64_t
1646 parse_fixed_uint64 (const uint8_t *data)
1647 {
1648 #if IS_LITTLE_ENDIAN
1649   uint64_t t;
1650   memcpy (&t, data, 8);
1651   return t;
1652 #else
1653   return (uint64_t)parse_fixed_uint32 (data)
1654       | (((uint64_t)parse_fixed_uint32(data+4)) << 32);
1655 #endif
1656 }
1657 static protobuf_c_boolean
1658 parse_boolean (unsigned len, const uint8_t *data)
1659 {
1660   unsigned i;
1661   for (i = 0; i < len; i++)
1662     if (data[i] & 0x7f)
1663       return 1;
1664   return 0;
1665 }
1666 static protobuf_c_boolean
1667 parse_required_member (ScannedMember *scanned_member,
1668                        void *member,
1669                        ProtobufCAllocator *allocator,
1670                        protobuf_c_boolean maybe_clear)
1671 {
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)
1676     {
1677     case PROTOBUF_C_TYPE_INT32:
1678       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1679         return 0;
1680       *(uint32_t*)member = parse_int32 (len, data);
1681       return 1;
1682     case PROTOBUF_C_TYPE_UINT32:
1683       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1684         return 0;
1685       *(uint32_t*)member = parse_uint32 (len, data);
1686       return 1;
1687     case PROTOBUF_C_TYPE_SINT32:
1688       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1689         return 0;
1690       *(int32_t*)member = unzigzag32 (parse_uint32 (len, data));
1691       return 1;
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)
1696         return 0;
1697       *(uint32_t*)member = parse_fixed_uint32 (data);
1698       return 1;
1699
1700     case PROTOBUF_C_TYPE_INT64:
1701     case PROTOBUF_C_TYPE_UINT64:
1702       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1703         return 0;
1704       *(uint64_t*)member = parse_uint64 (len, data);
1705       return 1;
1706     case PROTOBUF_C_TYPE_SINT64:
1707       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1708         return 0;
1709       *(int64_t*)member = unzigzag64 (parse_uint64 (len, data));
1710       return 1;
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)
1715         return 0;
1716       *(uint64_t*)member = parse_fixed_uint64 (data);
1717       return 1;
1718
1719     case PROTOBUF_C_TYPE_BOOL:
1720       *(protobuf_c_boolean*)member = parse_boolean (len, data);
1721       return 1;
1722
1723     case PROTOBUF_C_TYPE_ENUM:
1724       if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
1725         return 0;
1726       *(uint32_t*)member = parse_uint32 (len, data);
1727       return 1;
1728
1729     case PROTOBUF_C_TYPE_STRING:
1730       if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1731         return 0;
1732       {
1733         char **pstr = member;
1734         unsigned pref_len = scanned_member->length_prefix_len;
1735         if (maybe_clear && *pstr != NULL)
1736           {
1737             const char *def = scanned_member->field->default_value;
1738             if (*pstr != NULL && *pstr != def)
1739               FREE (allocator, *pstr);
1740           }
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;
1744         return 1;
1745       }
1746     case PROTOBUF_C_TYPE_BYTES:
1747       if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1748         return 0;
1749       {
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;
1759         return 1;
1760       }
1761     //case PROTOBUF_C_TYPE_GROUP,          // NOT SUPPORTED
1762     case PROTOBUF_C_TYPE_MESSAGE:
1763       if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
1764         return 0;
1765       {
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,
1774                                           allocator,
1775                                           len - pref_len, data + pref_len);
1776         *pmessage = subm;       /* since we freed the message we must clear the field, even if NULL */
1777         if (subm == NULL)
1778           return 0;
1779         return 1;
1780       }
1781     }
1782   return 0;
1783 }
1784
1785 static protobuf_c_boolean
1786 parse_optional_member (ScannedMember *scanned_member,
1787                        void *member,
1788                        ProtobufCMessage *message,
1789                        ProtobufCAllocator *allocator)
1790 {
1791   if (!parse_required_member (scanned_member, member, allocator, TRUE))
1792     return 0;
1793   if (scanned_member->field->quantifier_offset != 0)
1794     STRUCT_MEMBER (protobuf_c_boolean,
1795                    message,
1796                    scanned_member->field->quantifier_offset) = 1;
1797   return 1;
1798 }
1799
1800 static protobuf_c_boolean
1801 parse_repeated_member (ScannedMember *scanned_member,
1802                        void *member,
1803                        ProtobufCMessage *message,
1804                        ProtobufCAllocator *allocator)
1805 {
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),
1812                               allocator,
1813                               FALSE))
1814     return 0;
1815   *p_n += 1;
1816   return 1;
1817 }
1818
1819 static unsigned scan_varint (unsigned len, const uint8_t *data)
1820 {
1821   unsigned i;
1822   if (len > 10)
1823     len = 10;
1824   for (i = 0; i < len; i++)
1825     if ((data[i] & 0x80) == 0)
1826       break;
1827   if (i == len)
1828     return 0;
1829   return i + 1;
1830 }
1831
1832 static protobuf_c_boolean
1833 parse_packed_repeated_member (ScannedMember *scanned_member,
1834                               void *member,
1835                               ProtobufCMessage *message)
1836 {
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;
1843   size_t count = 0;
1844   unsigned i;
1845   switch (field->type)
1846     {
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;
1853 #else
1854         for (i = 0; i < count; i++)
1855           {
1856             ((uint32_t*)array)[i] = parse_fixed_uint32 (at);
1857             at += 4;
1858           }
1859 #endif
1860         break;
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;
1867 #else
1868         for (i = 0; i < count; i++)
1869           {
1870             ((uint64_t*)array)[i] = parse_fixed_uint64 (at);
1871             at += 8;
1872           }
1873         break;
1874 #endif
1875       case PROTOBUF_C_TYPE_INT32:
1876         while (rem > 0)
1877           {
1878             unsigned s = scan_varint (rem, at);
1879             if (s == 0)
1880               {
1881                 UNPACK_ERROR (("bad packed-repeated int32 value"));
1882                 return FALSE;
1883               }
1884             ((int32_t*)array)[count++] = parse_int32 (s, at);
1885             at += s;
1886             rem -= s;
1887           }
1888         break;
1889
1890       case PROTOBUF_C_TYPE_SINT32:
1891         while (rem > 0)
1892           {
1893             unsigned s = scan_varint (rem, at);
1894             if (s == 0)
1895               {
1896                 UNPACK_ERROR (("bad packed-repeated sint32 value"));
1897                 return FALSE;
1898               }
1899             ((int32_t*)array)[count++] = unzigzag32 (parse_uint32 (s, at));
1900             at += s;
1901             rem -= s;
1902           }
1903         break;
1904       case PROTOBUF_C_TYPE_ENUM:
1905       case PROTOBUF_C_TYPE_UINT32:
1906         while (rem > 0)
1907           {
1908             unsigned s = scan_varint (rem, at);
1909             if (s == 0)
1910               {
1911                 UNPACK_ERROR (("bad packed-repeated enum or uint32 value"));
1912                 return FALSE;
1913               }
1914             ((uint32_t*)array)[count++] = parse_uint32 (s, at);
1915             at += s;
1916             rem -= s;
1917           }
1918         break;
1919
1920       case PROTOBUF_C_TYPE_SINT64:
1921         while (rem > 0)
1922           {
1923             unsigned s = scan_varint (rem, at);
1924             if (s == 0)
1925               {
1926                 UNPACK_ERROR (("bad packed-repeated sint64 value"));
1927                 return FALSE;
1928               }
1929             ((int64_t*)array)[count++] = unzigzag64 (parse_uint64 (s, at));
1930             at += s;
1931             rem -= s;
1932           }
1933         break;
1934       case PROTOBUF_C_TYPE_INT64:
1935       case PROTOBUF_C_TYPE_UINT64:
1936         while (rem > 0)
1937           {
1938             unsigned s = scan_varint (rem, at);
1939             if (s == 0)
1940               {
1941                 UNPACK_ERROR (("bad packed-repeated int64/uint64 value"));
1942                 return FALSE;
1943               }
1944             ((int64_t*)array)[count++] = parse_uint64 (s, at);
1945             at += s;
1946             rem -= s;
1947           }
1948         break;
1949       case PROTOBUF_C_TYPE_BOOL:
1950         count = rem;
1951         for (i = 0; i < count; i++)
1952           {
1953             if (at[i] > 1)
1954               {
1955                 UNPACK_ERROR (("bad packed-repeated boolean value"));
1956                 return FALSE;
1957               }
1958             ((protobuf_c_boolean*)array)[i] = at[i];
1959           }
1960         break;
1961       default:
1962         assert(0);
1963     }
1964   *p_n += count;
1965   return TRUE;
1966
1967 no_unpacking_needed:
1968   memcpy (array, at, count * siz);
1969   *p_n += count;
1970   return TRUE;
1971 }
1972
1973 static protobuf_c_boolean
1974 parse_member (ScannedMember *scanned_member,
1975               ProtobufCMessage *message,
1976               ProtobufCAllocator *allocator)
1977 {
1978   const ProtobufCFieldDescriptor *field = scanned_member->field;
1979   void *member;
1980   if (field == NULL)
1981     {
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);
1988       return 1;
1989     }
1990   member = (char*)message + field->offset;
1991   switch (field->label)
1992     {
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:
1998       if (field->packed
1999        && scanned_member->wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2000         return parse_packed_repeated_member (scanned_member, member, message);
2001       else
2002         return parse_repeated_member (scanned_member, member, message, allocator);
2003     }
2004   PROTOBUF_C_ASSERT_NOT_REACHED ();
2005   return 0;
2006 }
2007
2008
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). */
2012 void
2013 protobuf_c_message_init_generic (const ProtobufCMessageDescriptor *desc,
2014                                  ProtobufCMessage *message)
2015 {
2016   unsigned i;
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)
2022       {
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)
2026         {
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);
2035           break;
2036
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);
2044           break;
2045
2046         case PROTOBUF_C_TYPE_BOOL:
2047           memcpy (field, dv, sizeof (protobuf_c_boolean));
2048           break;
2049
2050         case PROTOBUF_C_TYPE_BYTES:
2051           memcpy (field, dv, sizeof (ProtobufCBinaryData));
2052           break;
2053
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;
2059           break;
2060         }
2061       }
2062 }
2063
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).
2068
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
2075
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)
2083
2084 ProtobufCMessage *
2085 protobuf_c_message_unpack         (const ProtobufCMessageDescriptor *desc,
2086                                    ProtobufCAllocator  *allocator,
2087                                    size_t               len,
2088                                    const uint8_t       *data)
2089 {
2090   ProtobufCMessage *rv;
2091   size_t rem = len;
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];
2095
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;
2104   unsigned f;
2105   unsigned i_slab;
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;
2110
2111   ASSERT_IS_MESSAGE_DESCRIPTOR (desc);
2112
2113   if (allocator == NULL)
2114     allocator = &protobuf_c_default_allocator;
2115
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));
2119
2120   DO_ALLOC (rv, allocator, desc->sizeof_message, return NULL);
2121   scanned_member_slabs[0] = first_member_slab;
2122
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);
2130   else
2131     protobuf_c_message_init_generic (desc, rv);
2132
2133   while (rem > 0)
2134     {
2135       uint32_t tag;
2136       ProtobufCWireType wire_type;
2137       size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
2138       const ProtobufCFieldDescriptor *field;
2139       ScannedMember tmp;
2140       if (used == 0)
2141         {
2142           UNPACK_ERROR (("error parsing tag/wiretype at offset %u",
2143                          (unsigned)(at-data)));
2144           goto error_cleanup_during_scan;
2145         }
2146       /* XXX: consider optimizing for field[1].id == tag, if field[1] exists! */
2147       if (last_field->id != tag)
2148         {
2149           /* lookup field */
2150           int field_index = int_range_lookup (desc->n_field_ranges,
2151                                               desc->field_ranges,
2152                                               tag);
2153           if (field_index < 0)
2154             {
2155               field = NULL;
2156               n_unknown++;
2157             }
2158           else
2159             {
2160               field = desc->fields + field_index;
2161               last_field = field;
2162               last_field_index = field_index;
2163             }
2164         }
2165       else
2166         field = last_field;
2167
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));
2170
2171       at += used;
2172       rem -= used;
2173       tmp.tag = tag;
2174       tmp.wire_type = wire_type;
2175       tmp.field = field;
2176       tmp.data = at;
2177       switch (wire_type)
2178         {
2179         case PROTOBUF_C_WIRE_TYPE_VARINT:
2180           {
2181             unsigned max_len = rem < 10 ? rem : 10;
2182             unsigned i;
2183             for (i = 0; i < max_len; i++)
2184               if ((at[i] & 0x80) == 0)
2185                 break;
2186             if (i == max_len)
2187               {
2188                 UNPACK_ERROR (("unterminated varint at offset %u",
2189                                (unsigned)(at-data)));
2190                 goto error_cleanup_during_scan;
2191               }
2192             tmp.len = i + 1;
2193           }
2194           break;
2195         case PROTOBUF_C_WIRE_TYPE_64BIT:
2196           if (rem < 8)
2197             {
2198               UNPACK_ERROR (("too short after 64bit wiretype at offset %u",
2199                              (unsigned)(at-data)));
2200               goto error_cleanup_during_scan;
2201             }
2202           tmp.len = 8;
2203           break;
2204         case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED:
2205           {
2206             size_t pref_len;
2207             tmp.len = scan_length_prefixed_data (rem, at, &pref_len);
2208             if (tmp.len == 0)
2209               {
2210                 /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
2211                 goto error_cleanup_during_scan;
2212               }
2213             tmp.length_prefix_len = pref_len;
2214             break;
2215           }
2216         case PROTOBUF_C_WIRE_TYPE_32BIT:
2217           if (rem < 4)
2218             {
2219               UNPACK_ERROR (("too short after 32bit wiretype at offset %u",
2220                              (unsigned)(at-data)));
2221               goto error_cleanup_during_scan;
2222             }
2223           tmp.len = 4;
2224           break;
2225         default:
2226           UNPACK_ERROR (("unsupported tag %u at offset %u",
2227                          wire_type, (unsigned)(at-data))); 
2228           goto error_cleanup_during_scan;
2229         }
2230       if (in_slab_index == (1U<<(which_slab+FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
2231         {
2232           size_t size;
2233           in_slab_index = 0;
2234           if (which_slab == MAX_SCANNED_MEMBER_SLAB)
2235             {
2236               UNPACK_ERROR (("too many fields"));
2237               goto error_cleanup_during_scan;
2238             }
2239           which_slab++;
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);
2244           else
2245             DO_ALLOC (scanned_member_slabs[which_slab], allocator, size, goto error_cleanup_during_scan);
2246         }
2247       scanned_member_slabs[which_slab][in_slab_index++] = tmp;
2248
2249       if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED)
2250         {
2251           size_t *n = STRUCT_MEMBER_PTR (size_t, rv, field->quantifier_offset);
2252           if (field->packed
2253            && wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2254             {
2255               size_t count;
2256               if (!count_packed_elements (field->type,
2257                                           tmp.len - tmp.length_prefix_len,
2258                                           tmp.data + tmp.length_prefix_len,
2259                                           &count))
2260                 {
2261                   UNPACK_ERROR (("counting packed elements"));
2262                   goto error_cleanup_during_scan;
2263                 }
2264               *n += count;
2265             }
2266           else
2267            *n += 1;
2268         }
2269
2270       at += tmp.len;
2271       rem -= tmp.len;
2272     }
2273
2274   /* allocate space for repeated fields, also check that all required fields have been set */
2275   for (f = 0; f < desc->n_fields; f++)
2276   {
2277     const ProtobufCFieldDescriptor *field = desc->fields + f;
2278     if (field->label == PROTOBUF_C_LABEL_REPEATED)
2279     {
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);
2282         if (*n_ptr != 0)
2283           {
2284             unsigned n = *n_ptr;
2285             *n_ptr = 0;
2286             assert(rv->descriptor != NULL);
2287 #define CLEAR_REMAINING_N_PTRS()                                            \
2288             for(f++;f < desc->n_fields; f++)                                \
2289               {                                                             \
2290                 field = desc->fields + f;                                   \
2291                 if (field->label == PROTOBUF_C_LABEL_REPEATED)              \
2292                   STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
2293               }
2294             DO_ALLOC (STRUCT_MEMBER (void *, rv, field->offset),
2295                       allocator, siz * n,
2296                       CLEAR_REMAINING_N_PTRS (); goto error_cleanup);
2297 #undef CLEAR_REMAINING_N_PTRS
2298           }
2299     }
2300     else if (field->label == PROTOBUF_C_LABEL_REQUIRED)
2301     {
2302       if (field->default_value == NULL && 0 == (required_fields_bitmap[f / word_bits] & (1UL << (f % word_bits))))
2303       {
2304         UNPACK_ERROR (("message '%s': missing required field '%s'", desc->name, field->name));
2305         goto error_cleanup;
2306       }
2307     }
2308   }
2309
2310   /* allocate space for unknown fields */
2311   if (n_unknown)
2312     {
2313       DO_ALLOC (rv->unknown_fields,
2314                 allocator, n_unknown * sizeof (ProtobufCMessageUnknownField),
2315                 goto error_cleanup);
2316     }
2317
2318   /* do real parsing */
2319   for (i_slab = 0; i_slab <= which_slab; i_slab++)
2320     {
2321       unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
2322       ScannedMember *slab = scanned_member_slabs[i_slab];
2323       unsigned j;
2324       for (j = 0; j < max; j++)
2325         {
2326           if (!parse_member (slab + j, rv, allocator))
2327             {
2328               UNPACK_ERROR (("error parsing member %s of %s",
2329                              slab->field ? slab->field->name : "*unknown-field*", desc->name));
2330               goto error_cleanup;
2331             }
2332         }
2333     }
2334
2335   /* cleanup */
2336   if (allocator->tmp_alloc == NULL)
2337     {
2338       unsigned j;
2339       for (j = 1; j <= which_slab; j++)
2340         FREE (allocator, scanned_member_slabs[j]);
2341     }
2342
2343   return rv;
2344
2345 error_cleanup:
2346   protobuf_c_message_free_unpacked (rv, allocator);
2347   if (allocator->tmp_alloc == NULL)
2348     {
2349       unsigned j;
2350       for (j = 1; j <= which_slab; j++)
2351         FREE (allocator, scanned_member_slabs[j]);
2352     }
2353   return NULL;
2354
2355 error_cleanup_during_scan:
2356   FREE (allocator, rv);
2357   if (allocator->tmp_alloc == NULL)
2358     {
2359       unsigned j;
2360       for (j = 1; j <= which_slab; j++)
2361         FREE (allocator, scanned_member_slabs[j]);
2362     }
2363   return NULL;
2364 }
2365
2366 /* === free_unpacked === */
2367 void     
2368 protobuf_c_message_free_unpacked  (ProtobufCMessage    *message,
2369                                    ProtobufCAllocator  *allocator)
2370 {
2371   const ProtobufCMessageDescriptor *desc = message->descriptor;
2372   unsigned f;
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++)
2378     {
2379       if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED)
2380         {
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)
2384             {
2385               unsigned i;
2386               for (i = 0; i < n; i++)
2387                 FREE (allocator, ((char**)arr)[i]);
2388             }
2389           else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
2390             {
2391               unsigned i;
2392               for (i = 0; i < n; i++)
2393                 FREE (allocator, ((ProtobufCBinaryData*)arr)[i].data);
2394             }
2395           else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
2396             {
2397               unsigned i;
2398               for (i = 0; i < n; i++)
2399                 protobuf_c_message_free_unpacked (((ProtobufCMessage**)arr)[i], allocator);
2400             }
2401           if (arr != NULL)
2402             FREE (allocator, arr);
2403         }
2404       else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING)
2405         {
2406           char *str = STRUCT_MEMBER (char *, message, desc->fields[f].offset);
2407           if (str && str != desc->fields[f].default_value)
2408             FREE (allocator, str);
2409         }
2410       else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES)
2411         {
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;
2415           if (data != NULL
2416            && (default_bd == NULL || default_bd->data != data))
2417             FREE (allocator, data);
2418         }
2419       else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE)
2420         {
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);
2425         }
2426     }
2427
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);
2432
2433   FREE (allocator, message);
2434 }
2435
2436 /* === services === */
2437 typedef void (*GenericHandler)(void *service,
2438                                const ProtobufCMessage *input,
2439                                ProtobufCClosure  closure,
2440                                void             *closure_data);
2441 void 
2442 protobuf_c_service_invoke_internal(ProtobufCService *service,
2443                                   unsigned          method_index,
2444                                   const ProtobufCMessage *input,
2445                                   ProtobufCClosure  closure,
2446                                   void             *closure_data)
2447 {
2448   GenericHandler *handlers;
2449   GenericHandler handler;
2450
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);
2456
2457   /* Get the array of virtual methods (which are enumerated by 
2458      the generated code) */
2459   handlers = (GenericHandler *) (service + 1);
2460
2461   /* get our method and invoke it */
2462   /* TODO: seems like handler==NULL is a situation that
2463      needs handling */
2464   handler = handlers[method_index];
2465   (*handler) (service, input, closure, closure_data);
2466 }
2467
2468 void
2469 protobuf_c_service_generated_init (ProtobufCService *service,
2470                                    const ProtobufCServiceDescriptor *descriptor,
2471                                    ProtobufCServiceDestroy destroy)
2472 {
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));
2478 }
2479
2480 void protobuf_c_service_destroy (ProtobufCService *service)
2481 {
2482   service->destroy (service);
2483 }
2484
2485 /* --- querying the descriptors --- */
2486 const ProtobufCEnumValue *
2487 protobuf_c_enum_descriptor_get_value_by_name 
2488                          (const ProtobufCEnumDescriptor    *desc,
2489                           const char                       *name)
2490 {
2491   unsigned start = 0, count = desc->n_value_names;
2492   while (count > 1)
2493     {
2494       unsigned mid = start + count / 2;
2495       int rv = strcmp (desc->values_by_name[mid].name, name);
2496       if (rv == 0)
2497         return desc->values + desc->values_by_name[mid].index;
2498       else if (rv < 0)
2499         {
2500           count = start + count - (mid + 1);
2501           start = mid + 1;
2502         }
2503       else
2504         count = mid - start;
2505     }
2506   if (count == 0)
2507     return NULL;
2508   if (strcmp (desc->values_by_name[start].name, name) == 0)
2509     return desc->values + desc->values_by_name[start].index;
2510   return NULL;
2511 }
2512 const ProtobufCEnumValue *
2513 protobuf_c_enum_descriptor_get_value        
2514                          (const ProtobufCEnumDescriptor    *desc,
2515                           int                               value)
2516 {
2517   int rv = int_range_lookup (desc->n_value_ranges, desc->value_ranges, value);
2518   if (rv < 0)
2519     return NULL;
2520   return desc->values + rv;
2521 }
2522
2523 const ProtobufCFieldDescriptor *
2524 protobuf_c_message_descriptor_get_field_by_name
2525                          (const ProtobufCMessageDescriptor *desc,
2526                           const char                       *name)
2527 {
2528   unsigned start = 0, count = desc->n_fields;
2529   const ProtobufCFieldDescriptor *field;
2530   while (count > 1)
2531     {
2532       unsigned mid = start + count / 2;
2533       int rv;
2534       field = desc->fields + desc->fields_sorted_by_name[mid];
2535       rv = strcmp (field->name, name);
2536       if (rv == 0)
2537         return field;
2538       else if (rv < 0)
2539         {
2540           count = start + count - (mid + 1);
2541           start = mid + 1;
2542         }
2543       else
2544         count = mid - start;
2545     }
2546   if (count == 0)
2547     return NULL;
2548   field = desc->fields + desc->fields_sorted_by_name[start];
2549   if (strcmp (field->name, name) == 0)
2550     return field;
2551   return NULL;
2552 }
2553
2554 const ProtobufCFieldDescriptor *
2555 protobuf_c_message_descriptor_get_field        
2556                          (const ProtobufCMessageDescriptor *desc,
2557                           unsigned                          value)
2558 {
2559   int rv = int_range_lookup (desc->n_field_ranges,
2560                              desc->field_ranges,
2561                              value);
2562   if (rv < 0)
2563     return NULL;
2564   return desc->fields + rv;
2565 }
2566
2567 const ProtobufCMethodDescriptor *
2568 protobuf_c_service_descriptor_get_method_by_name
2569                          (const ProtobufCServiceDescriptor *desc,
2570                           const char                       *name)
2571 {
2572   unsigned start = 0, count = desc->n_methods;
2573   while (count > 1)
2574     {
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);
2579       if (rv == 0)
2580         return desc->methods + desc->method_indices_by_name[mid];
2581       if (rv < 0)
2582         {
2583           count = start + count - (mid + 1);
2584           start = mid + 1;
2585         }
2586       else
2587         {
2588           count = mid - start;
2589         }
2590     }
2591   if (count == 0)
2592     return NULL;
2593   if (strcmp (desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
2594     return desc->methods + desc->method_indices_by_name[start];
2595   return NULL;
2596 }