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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 30 Revision 31
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
61static void
62alloc_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
96static void protobuf_c_out_of_memory_default (void)
97{
98 fprintf (stderr, "Out Of Memory!!!\n");
99 abort ();
100}
101void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
102
103static 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
115static 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. */
125ProtobufCAllocator 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. */
138ProtobufCAllocator protobuf_c_system_allocator =
139{
140 system_alloc,
141 system_free,
142 NULL,
143 8192,
144 NULL
145};
146
147/* === buffer-simple === */
148void
149protobuf_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. */
179static inline size_t
180get_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. */
197static inline size_t
198uint32_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. */
214static inline size_t
215int32_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 */
231static inline uint32_t
232zigzag32 (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. */
243static inline size_t
244sint32_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. */
252static inline size_t
253uint64_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 */
273static inline uint64_t
274zigzag64 (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. */
286static inline size_t
287sint64_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. */
294static size_t
295required_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. */
353static size_t
354optional_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). */
377static size_t
378repeated_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). */
460static inline size_t
461unknown_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. */
467size_t
468protobuf_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. */
493static inline size_t
494uint32_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. */
524static inline size_t
525int32_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. */
543static inline size_t
544sint32_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. */
551static size_t
552uint64_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) */
586static inline size_t
587sint64_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) */
594static inline size_t
595fixed32_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. */
613static inline size_t
614fixed64_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. */
630static inline size_t
631boolean_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 */
646static inline size_t
647string_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
663static inline size_t
664binary_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
672static inline size_t
673prefixed_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. */
692static size_t
693tag_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
701static size_t
702required_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}
762static size_t
763optional_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 */
785static inline size_t
786sizeof_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
817static void
818copy_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}
829static void
830copy_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
842static unsigned
843get_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
856static size_t
857repeated_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}
972static size_t
973unknown_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
982size_t
983protobuf_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() === */
1017static size_t
1018required_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}
1121static size_t
1122optional_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
1143static size_t
1144get_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}
1208static size_t
1209pack_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
1306no_packing_needed:
1307 buffer->append (buffer, rv, array);
1308 return rv;
1309}
1310
1311static size_t
1312repeated_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
1349static size_t
1350unknown_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
1361size_t
1362protobuf_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
1394static inline int
1395int_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
1432static size_t
1433parse_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
1465typedef struct _ScannedMember ScannedMember;
1466struct _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
1476static inline uint32_t
1477scan_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
1507static size_t
1508max_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() */
1523static protobuf_c_boolean
1524count_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
1575static inline uint32_t
1576parse_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}
1595static inline uint32_t
1596parse_int32 (unsigned len, const uint8_t *data)
1597{
1598 return parse_uint32 (len, data);
1599}
1600static inline int32_t
1601unzigzag32 (uint32_t v)
1602{
1603 if (v&1)
1604 return -(v>>1) - 1;
1605 else
1606 return v>>1;
1607}
1608static inline uint32_t
1609parse_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}
1619static uint64_t
1620parse_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}
1637static inline int64_t
1638unzigzag64 (uint64_t v)
1639{
1640 if (v&1)
1641 return -(v>>1) - 1;
1642 else
1643 return v>>1;
1644}
1645static inline uint64_t
1646parse_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}
1657static protobuf_c_boolean
1658parse_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}
1666static protobuf_c_boolean
1667parse_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
1785static protobuf_c_boolean
1786parse_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
1800static protobuf_c_boolean
1801parse_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
1819static 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
1832static protobuf_c_boolean
1833parse_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
1967no_unpacking_needed:
1968 memcpy (array, at, count * siz);
1969 *p_n += count;
1970 return TRUE;
1971}
1972
1973static protobuf_c_boolean
1974parse_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). */
2012void
2013protobuf_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
2084ProtobufCMessage *
2085protobuf_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
2345error_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
2355error_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 === */
2367void
2368protobuf_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 === */
2437typedef void (*GenericHandler)(void *service,
2438 const ProtobufCMessage *input,
2439 ProtobufCClosure closure,
2440 void *closure_data);
2441void
2442protobuf_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
2468void
2469protobuf_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
2480void protobuf_c_service_destroy (ProtobufCService *service)
2481{
2482 service->destroy (service);
2483}
2484
2485/* --- querying the descriptors --- */
2486const ProtobufCEnumValue *
2487protobuf_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}
2512const ProtobufCEnumValue *
2513protobuf_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
2523const ProtobufCFieldDescriptor *
2524protobuf_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
2554const ProtobufCFieldDescriptor *
2555protobuf_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
2567const ProtobufCMethodDescriptor *
2568protobuf_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}

Legend:
Removed from v.30  
changed lines
  Added in v.31

   
Visit the ZANavi Wiki