/[zanavi_public1]/navit/navit/maptool/google/protobuf-c/protobuf-c.c
ZANavi

Contents of /navit/navit/maptool/google/protobuf-c/protobuf-c.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations) (download)
Fri Oct 28 21:43:09 2011 UTC (8 years, 10 months ago) by zoff99
File MIME type: text/plain
File size: 80130 byte(s)
import
1 zoff99 10 /* --- 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     }

   
Visit the ZANavi Wiki