Coverage Report

Created: 2024-02-11 06:29

/src/libpg_query/vendor/protobuf-c/protobuf-c.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2008-2015, Dave Benson and the protobuf-c authors.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are
7
 * met:
8
 *
9
 *     * Redistributions of source code must retain the above copyright
10
 * notice, this list of conditions and the following disclaimer.
11
 *
12
 *     * Redistributions in binary form must reproduce the above
13
 * copyright notice, this list of conditions and the following disclaimer
14
 * in the documentation and/or other materials provided with the
15
 * distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
/*! \file
31
 * Support library for `protoc-c` generated code.
32
 *
33
 * This file implements the public API used by the code generated
34
 * by `protoc-c`.
35
 *
36
 * \authors Dave Benson and the protobuf-c authors
37
 *
38
 * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
39
 */
40
41
/**
42
 * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
43
 * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
44
 *
45
 * \todo Use size_t consistently.
46
 */
47
48
#include <stdlib.h> /* for malloc, free */
49
#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
50
51
#include "protobuf-c.h"
52
53
0
#define TRUE        1
54
0
#define FALSE       0
55
56
0
#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
57
58
/* Workaround for Microsoft compilers. */
59
#ifdef _MSC_VER
60
# define inline __inline
61
#endif
62
63
/**
64
 * \defgroup internal Internal functions and macros
65
 *
66
 * These are not exported by the library but are useful to developers working
67
 * on `libprotobuf-c` itself.
68
 */
69
70
/**
71
 * \defgroup macros Utility macros for manipulating structures
72
 *
73
 * Macros and constants used to manipulate the base "classes" generated by
74
 * `protobuf-c`. They also define limits and check correctness.
75
 *
76
 * \ingroup internal
77
 * @{
78
 */
79
80
/** The maximum length of a 64-bit integer in varint encoding. */
81
#define MAX_UINT64_ENCODED_SIZE   10
82
83
#ifndef PROTOBUF_C_UNPACK_ERROR
84
# define PROTOBUF_C_UNPACK_ERROR(...)
85
#endif
86
87
#if !defined(_WIN32) || !defined(PROTOBUF_C_USE_SHARED_LIB)
88
const char protobuf_c_empty_string[] = "";
89
#endif
90
91
/**
92
 * Internal `ProtobufCMessage` manipulation macro.
93
 *
94
 * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
95
 * STRUCT_MEMBER_PTR().
96
 */
97
#define STRUCT_MEMBER_P(struct_p, struct_offset) \
98
0
    ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
99
100
/**
101
 * Return field in a `ProtobufCMessage` based on offset.
102
 *
103
 * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
104
 * Cast it to the passed type.
105
 */
106
#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
107
0
    (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
108
109
/**
110
 * Return field in a `ProtobufCMessage` based on offset.
111
 *
112
 * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
113
 * it to a pointer to the passed type.
114
 */
115
#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
116
0
    ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
117
118
/* Assertions for magic numbers. */
119
120
#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
121
  assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
122
123
#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
124
0
  assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
125
126
#define ASSERT_IS_MESSAGE(message) \
127
0
  ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
128
129
#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
130
0
  assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
131
132
/**@}*/
133
134
/* --- version --- */
135
136
const char *
137
protobuf_c_version(void)
138
0
{
139
0
  return PROTOBUF_C_VERSION;
140
0
}
141
142
uint32_t
143
protobuf_c_version_number(void)
144
0
{
145
0
  return PROTOBUF_C_VERSION_NUMBER;
146
0
}
147
148
/* --- allocator --- */
149
150
static void *
151
system_alloc(void *allocator_data, size_t size)
152
0
{
153
0
  (void)allocator_data;
154
0
  return malloc(size);
155
0
}
156
157
static void
158
system_free(void *allocator_data, void *data)
159
0
{
160
0
  (void)allocator_data;
161
0
  free(data);
162
0
}
163
164
static inline void *
165
do_alloc(ProtobufCAllocator *allocator, size_t size)
166
0
{
167
0
  return allocator->alloc(allocator->allocator_data, size);
168
0
}
169
170
static inline void
171
do_free(ProtobufCAllocator *allocator, void *data)
172
0
{
173
0
  if (data != NULL)
174
0
    allocator->free(allocator->allocator_data, data);
175
0
}
176
177
/*
178
 * This allocator uses the system's malloc() and free(). It is the default
179
 * allocator used if NULL is passed as the ProtobufCAllocator to an exported
180
 * function.
181
 */
182
static ProtobufCAllocator protobuf_c__allocator = {
183
  .alloc = &system_alloc,
184
  .free = &system_free,
185
  .allocator_data = NULL,
186
};
187
188
/* === buffer-simple === */
189
190
void
191
protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
192
        size_t len, const uint8_t *data)
193
0
{
194
0
  ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
195
0
  size_t new_len = simp->len + len;
196
197
0
  if (new_len > simp->alloced) {
198
0
    ProtobufCAllocator *allocator = simp->allocator;
199
0
    size_t new_alloced = simp->alloced * 2;
200
0
    uint8_t *new_data;
201
202
0
    if (allocator == NULL)
203
0
      allocator = &protobuf_c__allocator;
204
0
    while (new_alloced < new_len)
205
0
      new_alloced += new_alloced;
206
0
    new_data = do_alloc(allocator, new_alloced);
207
0
    if (!new_data)
208
0
      return;
209
0
    memcpy(new_data, simp->data, simp->len);
210
0
    if (simp->must_free_data)
211
0
      do_free(allocator, simp->data);
212
0
    else
213
0
      simp->must_free_data = TRUE;
214
0
    simp->data = new_data;
215
0
    simp->alloced = new_alloced;
216
0
  }
217
0
  memcpy(simp->data + simp->len, data, len);
218
0
  simp->len = new_len;
219
0
}
220
221
/**
222
 * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
223
 *
224
 * Routines mainly used by protobuf_c_message_get_packed_size().
225
 *
226
 * \ingroup internal
227
 * @{
228
 */
229
230
/**
231
 * Return the number of bytes required to store the tag for the field. Includes
232
 * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
233
 *
234
 * \param number
235
 *      Field tag to encode.
236
 * \return
237
 *      Number of bytes required.
238
 */
239
static inline size_t
240
get_tag_size(uint32_t number)
241
0
{
242
0
  if (number < (1UL << 4)) {
243
0
    return 1;
244
0
  } else if (number < (1UL << 11)) {
245
0
    return 2;
246
0
  } else if (number < (1UL << 18)) {
247
0
    return 3;
248
0
  } else if (number < (1UL << 25)) {
249
0
    return 4;
250
0
  } else {
251
0
    return 5;
252
0
  }
253
0
}
254
255
/**
256
 * Return the number of bytes required to store a variable-length unsigned
257
 * 32-bit integer in base-128 varint encoding.
258
 *
259
 * \param v
260
 *      Value to encode.
261
 * \return
262
 *      Number of bytes required.
263
 */
264
static inline size_t
265
uint32_size(uint32_t v)
266
0
{
267
0
  if (v < (1UL << 7)) {
268
0
    return 1;
269
0
  } else if (v < (1UL << 14)) {
270
0
    return 2;
271
0
  } else if (v < (1UL << 21)) {
272
0
    return 3;
273
0
  } else if (v < (1UL << 28)) {
274
0
    return 4;
275
0
  } else {
276
0
    return 5;
277
0
  }
278
0
}
279
280
/**
281
 * Return the number of bytes required to store a variable-length signed 32-bit
282
 * integer in base-128 varint encoding.
283
 *
284
 * \param v
285
 *      Value to encode.
286
 * \return
287
 *      Number of bytes required.
288
 */
289
static inline size_t
290
int32_size(int32_t v)
291
0
{
292
0
  if (v < 0) {
293
0
    return 10;
294
0
  } else if (v < (1L << 7)) {
295
0
    return 1;
296
0
  } else if (v < (1L << 14)) {
297
0
    return 2;
298
0
  } else if (v < (1L << 21)) {
299
0
    return 3;
300
0
  } else if (v < (1L << 28)) {
301
0
    return 4;
302
0
  } else {
303
0
    return 5;
304
0
  }
305
0
}
306
307
/**
308
 * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
309
 * integer.
310
 *
311
 * \param v
312
 *      Value to encode.
313
 * \return
314
 *      ZigZag encoded integer.
315
 */
316
static inline uint32_t
317
zigzag32(int32_t v)
318
0
{
319
  // Note:  the right-shift must be arithmetic
320
  // Note:  left shift must be unsigned because of overflow
321
0
  return ((uint32_t)(v) << 1) ^ (uint32_t)(v >> 31);
322
0
}
323
324
/**
325
 * Return the number of bytes required to store a signed 32-bit integer,
326
 * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
327
 * varint encoding.
328
 *
329
 * \param v
330
 *      Value to encode.
331
 * \return
332
 *      Number of bytes required.
333
 */
334
static inline size_t
335
sint32_size(int32_t v)
336
0
{
337
0
  return uint32_size(zigzag32(v));
338
0
}
339
340
/**
341
 * Return the number of bytes required to store a 64-bit unsigned integer in
342
 * base-128 varint encoding.
343
 *
344
 * \param v
345
 *      Value to encode.
346
 * \return
347
 *      Number of bytes required.
348
 */
349
static inline size_t
350
uint64_size(uint64_t v)
351
0
{
352
0
  uint32_t upper_v = (uint32_t) (v >> 32);
353
354
0
  if (upper_v == 0) {
355
0
    return uint32_size((uint32_t) v);
356
0
  } else if (upper_v < (1UL << 3)) {
357
0
    return 5;
358
0
  } else if (upper_v < (1UL << 10)) {
359
0
    return 6;
360
0
  } else if (upper_v < (1UL << 17)) {
361
0
    return 7;
362
0
  } else if (upper_v < (1UL << 24)) {
363
0
    return 8;
364
0
  } else if (upper_v < (1UL << 31)) {
365
0
    return 9;
366
0
  } else {
367
0
    return 10;
368
0
  }
369
0
}
370
371
/**
372
 * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
373
 * integer.
374
 *
375
 * \param v
376
 *      Value to encode.
377
 * \return
378
 *      ZigZag encoded integer.
379
 */
380
static inline uint64_t
381
zigzag64(int64_t v)
382
0
{
383
  // Note:  the right-shift must be arithmetic
384
  // Note:  left shift must be unsigned because of overflow
385
0
  return ((uint64_t)(v) << 1) ^ (uint64_t)(v >> 63);
386
0
}
387
388
/**
389
 * Return the number of bytes required to store a signed 64-bit integer,
390
 * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
391
 * varint encoding.
392
 *
393
 * \param v
394
 *      Value to encode.
395
 * \return
396
 *      Number of bytes required.
397
 */
398
static inline size_t
399
sint64_size(int64_t v)
400
0
{
401
0
  return uint64_size(zigzag64(v));
402
0
}
403
404
/**
405
 * Calculate the serialized size of a single required message field, including
406
 * the space needed by the preceding tag.
407
 *
408
 * \param field
409
 *      Field descriptor for member.
410
 * \param member
411
 *      Field to encode.
412
 * \return
413
 *      Number of bytes required.
414
 */
415
static size_t
416
required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
417
             const void *member)
418
0
{
419
0
  size_t rv = get_tag_size(field->id);
420
421
0
  switch (field->type) {
422
0
  case PROTOBUF_C_TYPE_SINT32:
423
0
    return rv + sint32_size(*(const int32_t *) member);
424
0
  case PROTOBUF_C_TYPE_ENUM:
425
0
  case PROTOBUF_C_TYPE_INT32:
426
0
    return rv + int32_size(*(const int32_t *) member);
427
0
  case PROTOBUF_C_TYPE_UINT32:
428
0
    return rv + uint32_size(*(const uint32_t *) member);
429
0
  case PROTOBUF_C_TYPE_SINT64:
430
0
    return rv + sint64_size(*(const int64_t *) member);
431
0
  case PROTOBUF_C_TYPE_INT64:
432
0
  case PROTOBUF_C_TYPE_UINT64:
433
0
    return rv + uint64_size(*(const uint64_t *) member);
434
0
  case PROTOBUF_C_TYPE_SFIXED32:
435
0
  case PROTOBUF_C_TYPE_FIXED32:
436
0
    return rv + 4;
437
0
  case PROTOBUF_C_TYPE_SFIXED64:
438
0
  case PROTOBUF_C_TYPE_FIXED64:
439
0
    return rv + 8;
440
0
  case PROTOBUF_C_TYPE_BOOL:
441
0
    return rv + 1;
442
0
  case PROTOBUF_C_TYPE_FLOAT:
443
0
    return rv + 4;
444
0
  case PROTOBUF_C_TYPE_DOUBLE:
445
0
    return rv + 8;
446
0
  case PROTOBUF_C_TYPE_STRING: {
447
0
    const char *str = *(char * const *) member;
448
0
    size_t len = str ? strlen(str) : 0;
449
0
    return rv + uint32_size(len) + len;
450
0
  }
451
0
  case PROTOBUF_C_TYPE_BYTES: {
452
0
    size_t len = ((const ProtobufCBinaryData *) member)->len;
453
0
    return rv + uint32_size(len) + len;
454
0
  }
455
0
  case PROTOBUF_C_TYPE_MESSAGE: {
456
0
    const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
457
0
    size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
458
0
    return rv + uint32_size(subrv) + subrv;
459
0
  }
460
0
  }
461
0
  PROTOBUF_C__ASSERT_NOT_REACHED();
462
0
  return 0;
463
0
}
464
465
/**
466
 * Calculate the serialized size of a single oneof message field, including
467
 * the space needed by the preceding tag. Returns 0 if the oneof field isn't
468
 * selected or is not set.
469
 *
470
 * \param field
471
 *      Field descriptor for member.
472
 * \param oneof_case
473
 *      Enum value that selects the field in the oneof.
474
 * \param member
475
 *      Field to encode.
476
 * \return
477
 *      Number of bytes required.
478
 */
479
static size_t
480
oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field,
481
          uint32_t oneof_case,
482
          const void *member)
483
0
{
484
0
  if (oneof_case != field->id) {
485
0
    return 0;
486
0
  }
487
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
488
0
      field->type == PROTOBUF_C_TYPE_STRING)
489
0
  {
490
0
    const void *ptr = *(const void * const *) member;
491
0
    if (ptr == NULL || ptr == field->default_value)
492
0
      return 0;
493
0
  }
494
0
  return required_field_get_packed_size(field, member);
495
0
}
496
497
/**
498
 * Calculate the serialized size of a single optional message field, including
499
 * the space needed by the preceding tag. Returns 0 if the optional field isn't
500
 * set.
501
 *
502
 * \param field
503
 *      Field descriptor for member.
504
 * \param has
505
 *      True if the field exists, false if not.
506
 * \param member
507
 *      Field to encode.
508
 * \return
509
 *      Number of bytes required.
510
 */
511
static size_t
512
optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
513
             const protobuf_c_boolean has,
514
             const void *member)
515
0
{
516
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
517
0
      field->type == PROTOBUF_C_TYPE_STRING)
518
0
  {
519
0
    const void *ptr = *(const void * const *) member;
520
0
    if (ptr == NULL || ptr == field->default_value)
521
0
      return 0;
522
0
  } else {
523
0
    if (!has)
524
0
      return 0;
525
0
  }
526
0
  return required_field_get_packed_size(field, member);
527
0
}
528
529
static protobuf_c_boolean
530
field_is_zeroish(const ProtobufCFieldDescriptor *field,
531
     const void *member)
532
0
{
533
0
  protobuf_c_boolean ret = FALSE;
534
535
0
  switch (field->type) {
536
0
  case PROTOBUF_C_TYPE_BOOL:
537
0
    ret = (0 == *(const protobuf_c_boolean *) member);
538
0
    break;
539
0
  case PROTOBUF_C_TYPE_ENUM:
540
0
  case PROTOBUF_C_TYPE_SINT32:
541
0
  case PROTOBUF_C_TYPE_INT32:
542
0
  case PROTOBUF_C_TYPE_UINT32:
543
0
  case PROTOBUF_C_TYPE_SFIXED32:
544
0
  case PROTOBUF_C_TYPE_FIXED32:
545
0
    ret = (0 == *(const uint32_t *) member);
546
0
    break;
547
0
  case PROTOBUF_C_TYPE_SINT64:
548
0
  case PROTOBUF_C_TYPE_INT64:
549
0
  case PROTOBUF_C_TYPE_UINT64:
550
0
  case PROTOBUF_C_TYPE_SFIXED64:
551
0
  case PROTOBUF_C_TYPE_FIXED64:
552
0
    ret = (0 == *(const uint64_t *) member);
553
0
    break;
554
0
  case PROTOBUF_C_TYPE_FLOAT:
555
0
    ret = (0 == *(const float *) member);
556
0
    break;
557
0
  case PROTOBUF_C_TYPE_DOUBLE:
558
0
    ret = (0 == *(const double *) member);
559
0
    break;
560
0
  case PROTOBUF_C_TYPE_STRING:
561
0
    ret = (NULL == *(const char * const *) member) ||
562
0
          ('\0' == **(const char * const *) member);
563
0
    break;
564
0
  case PROTOBUF_C_TYPE_BYTES:
565
0
  case PROTOBUF_C_TYPE_MESSAGE:
566
0
    ret = (NULL == *(const void * const *) member);
567
0
    break;
568
0
  default:
569
0
    ret = TRUE;
570
0
    break;
571
0
  }
572
573
0
  return ret;
574
0
}
575
576
/**
577
 * Calculate the serialized size of a single unlabeled message field, including
578
 * the space needed by the preceding tag. Returns 0 if the field isn't set or
579
 * if it is set to a "zeroish" value (null pointer or 0 for numerical values).
580
 * Unlabeled fields are supported only in proto3.
581
 *
582
 * \param field
583
 *      Field descriptor for member.
584
 * \param member
585
 *      Field to encode.
586
 * \return
587
 *      Number of bytes required.
588
 */
589
static size_t
590
unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field,
591
        const void *member)
592
0
{
593
0
  if (field_is_zeroish(field, member))
594
0
    return 0;
595
0
  return required_field_get_packed_size(field, member);
596
0
}
597
598
/**
599
 * Calculate the serialized size of repeated message fields, which may consist
600
 * of any number of values (including 0). Includes the space needed by the
601
 * preceding tags (as needed).
602
 *
603
 * \param field
604
 *      Field descriptor for member.
605
 * \param count
606
 *      Number of repeated field members.
607
 * \param member
608
 *      Field to encode.
609
 * \return
610
 *      Number of bytes required.
611
 */
612
static size_t
613
repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
614
             size_t count, const void *member)
615
0
{
616
0
  size_t header_size;
617
0
  size_t rv = 0;
618
0
  unsigned i;
619
0
  void *array = *(void * const *) member;
620
621
0
  if (count == 0)
622
0
    return 0;
623
0
  header_size = get_tag_size(field->id);
624
0
  if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
625
0
    header_size *= count;
626
627
0
  switch (field->type) {
628
0
  case PROTOBUF_C_TYPE_SINT32:
629
0
    for (i = 0; i < count; i++)
630
0
      rv += sint32_size(((int32_t *) array)[i]);
631
0
    break;
632
0
  case PROTOBUF_C_TYPE_ENUM:
633
0
  case PROTOBUF_C_TYPE_INT32:
634
0
    for (i = 0; i < count; i++)
635
0
      rv += int32_size(((int32_t *) array)[i]);
636
0
    break;
637
0
  case PROTOBUF_C_TYPE_UINT32:
638
0
    for (i = 0; i < count; i++)
639
0
      rv += uint32_size(((uint32_t *) array)[i]);
640
0
    break;
641
0
  case PROTOBUF_C_TYPE_SINT64:
642
0
    for (i = 0; i < count; i++)
643
0
      rv += sint64_size(((int64_t *) array)[i]);
644
0
    break;
645
0
  case PROTOBUF_C_TYPE_INT64:
646
0
  case PROTOBUF_C_TYPE_UINT64:
647
0
    for (i = 0; i < count; i++)
648
0
      rv += uint64_size(((uint64_t *) array)[i]);
649
0
    break;
650
0
  case PROTOBUF_C_TYPE_SFIXED32:
651
0
  case PROTOBUF_C_TYPE_FIXED32:
652
0
  case PROTOBUF_C_TYPE_FLOAT:
653
0
    rv += 4 * count;
654
0
    break;
655
0
  case PROTOBUF_C_TYPE_SFIXED64:
656
0
  case PROTOBUF_C_TYPE_FIXED64:
657
0
  case PROTOBUF_C_TYPE_DOUBLE:
658
0
    rv += 8 * count;
659
0
    break;
660
0
  case PROTOBUF_C_TYPE_BOOL:
661
0
    rv += count;
662
0
    break;
663
0
  case PROTOBUF_C_TYPE_STRING:
664
0
    for (i = 0; i < count; i++) {
665
0
      size_t len = strlen(((char **) array)[i]);
666
0
      rv += uint32_size(len) + len;
667
0
    }
668
0
    break;
669
0
  case PROTOBUF_C_TYPE_BYTES:
670
0
    for (i = 0; i < count; i++) {
671
0
      size_t len = ((ProtobufCBinaryData *) array)[i].len;
672
0
      rv += uint32_size(len) + len;
673
0
    }
674
0
    break;
675
0
  case PROTOBUF_C_TYPE_MESSAGE:
676
0
    for (i = 0; i < count; i++) {
677
0
      size_t len = protobuf_c_message_get_packed_size(
678
0
        ((ProtobufCMessage **) array)[i]);
679
0
      rv += uint32_size(len) + len;
680
0
    }
681
0
    break;
682
0
  }
683
684
0
  if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
685
0
    header_size += uint32_size(rv);
686
0
  return header_size + rv;
687
0
}
688
689
/**
690
 * Calculate the serialized size of an unknown field, i.e. one that is passed
691
 * through mostly uninterpreted. This is required for forward compatibility if
692
 * new fields are added to the message descriptor.
693
 *
694
 * \param field
695
 *      Unknown field type.
696
 * \return
697
 *      Number of bytes required.
698
 */
699
static inline size_t
700
unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
701
0
{
702
0
  return get_tag_size(field->tag) + field->len;
703
0
}
704
705
/**@}*/
706
707
/*
708
 * Calculate the serialized size of the message.
709
 */
710
size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
711
0
{
712
0
  unsigned i;
713
0
  size_t rv = 0;
714
715
0
  ASSERT_IS_MESSAGE(message);
716
0
  for (i = 0; i < message->descriptor->n_fields; i++) {
717
0
    const ProtobufCFieldDescriptor *field =
718
0
      message->descriptor->fields + i;
719
0
    const void *member =
720
0
      ((const char *) message) + field->offset;
721
0
    const void *qmember =
722
0
      ((const char *) message) + field->quantifier_offset;
723
724
0
    if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
725
0
      rv += required_field_get_packed_size(field, member);
726
0
    } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
727
0
          field->label == PROTOBUF_C_LABEL_NONE) &&
728
0
         (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
729
0
      rv += oneof_field_get_packed_size(
730
0
        field,
731
0
        *(const uint32_t *) qmember,
732
0
        member
733
0
      );
734
0
    } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
735
0
      rv += optional_field_get_packed_size(
736
0
        field,
737
0
        *(protobuf_c_boolean *) qmember,
738
0
        member
739
0
      );
740
0
    } else if (field->label == PROTOBUF_C_LABEL_NONE) {
741
0
      rv += unlabeled_field_get_packed_size(
742
0
        field,
743
0
        member
744
0
      );
745
0
    } else {
746
0
      rv += repeated_field_get_packed_size(
747
0
        field,
748
0
        *(const size_t *) qmember,
749
0
        member
750
0
      );
751
0
    }
752
0
  }
753
0
  for (i = 0; i < message->n_unknown_fields; i++)
754
0
    rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
755
0
  return rv;
756
0
}
757
758
/**
759
 * \defgroup pack protobuf_c_message_pack() implementation
760
 *
761
 * Routines mainly used by protobuf_c_message_pack().
762
 *
763
 * \ingroup internal
764
 * @{
765
 */
766
767
/**
768
 * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
769
 * number of bytes written, which must be 5 or less.
770
 *
771
 * \param value
772
 *      Value to encode.
773
 * \param[out] out
774
 *      Packed value.
775
 * \return
776
 *      Number of bytes written to `out`.
777
 */
778
static inline size_t
779
uint32_pack(uint32_t value, uint8_t *out)
780
0
{
781
0
  unsigned rv = 0;
782
783
0
  if (value >= 0x80) {
784
0
    out[rv++] = value | 0x80;
785
0
    value >>= 7;
786
0
    if (value >= 0x80) {
787
0
      out[rv++] = value | 0x80;
788
0
      value >>= 7;
789
0
      if (value >= 0x80) {
790
0
        out[rv++] = value | 0x80;
791
0
        value >>= 7;
792
0
        if (value >= 0x80) {
793
0
          out[rv++] = value | 0x80;
794
0
          value >>= 7;
795
0
        }
796
0
      }
797
0
    }
798
0
  }
799
  /* assert: value<128 */
800
0
  out[rv++] = value;
801
0
  return rv;
802
0
}
803
804
/**
805
 * Pack a signed 32-bit integer and return the number of bytes written.
806
 * Negative numbers are encoded as two's complement 64-bit integers.
807
 *
808
 * \param value
809
 *      Value to encode.
810
 * \param[out] out
811
 *      Packed value.
812
 * \return
813
 *      Number of bytes written to `out`.
814
 */
815
static inline size_t
816
int32_pack(int32_t value, uint8_t *out)
817
0
{
818
0
  if (value < 0) {
819
0
    out[0] = value | 0x80;
820
0
    out[1] = (value >> 7) | 0x80;
821
0
    out[2] = (value >> 14) | 0x80;
822
0
    out[3] = (value >> 21) | 0x80;
823
0
    out[4] = (value >> 28) | 0x80;
824
0
    out[5] = out[6] = out[7] = out[8] = 0xff;
825
0
    out[9] = 0x01;
826
0
    return 10;
827
0
  } else {
828
0
    return uint32_pack(value, out);
829
0
  }
830
0
}
831
832
/**
833
 * Pack a signed 32-bit integer using ZigZag encoding and return the number of
834
 * bytes written.
835
 *
836
 * \param value
837
 *      Value to encode.
838
 * \param[out] out
839
 *      Packed value.
840
 * \return
841
 *      Number of bytes written to `out`.
842
 */
843
static inline size_t
844
sint32_pack(int32_t value, uint8_t *out)
845
0
{
846
0
  return uint32_pack(zigzag32(value), out);
847
0
}
848
849
/**
850
 * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
851
 * number of bytes written.
852
 *
853
 * \param value
854
 *      Value to encode.
855
 * \param[out] out
856
 *      Packed value.
857
 * \return
858
 *      Number of bytes written to `out`.
859
 */
860
static size_t
861
uint64_pack(uint64_t value, uint8_t *out)
862
0
{
863
0
  uint32_t hi = (uint32_t) (value >> 32);
864
0
  uint32_t lo = (uint32_t) value;
865
0
  unsigned rv;
866
867
0
  if (hi == 0)
868
0
    return uint32_pack((uint32_t) lo, out);
869
0
  out[0] = (lo) | 0x80;
870
0
  out[1] = (lo >> 7) | 0x80;
871
0
  out[2] = (lo >> 14) | 0x80;
872
0
  out[3] = (lo >> 21) | 0x80;
873
0
  if (hi < 8) {
874
0
    out[4] = (hi << 4) | (lo >> 28);
875
0
    return 5;
876
0
  } else {
877
0
    out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
878
0
    hi >>= 3;
879
0
  }
880
0
  rv = 5;
881
0
  while (hi >= 128) {
882
0
    out[rv++] = hi | 0x80;
883
0
    hi >>= 7;
884
0
  }
885
0
  out[rv++] = hi;
886
0
  return rv;
887
0
}
888
889
/**
890
 * Pack a 64-bit signed integer in ZigZag encoding and return the number of
891
 * bytes written.
892
 *
893
 * \param value
894
 *      Value to encode.
895
 * \param[out] out
896
 *      Packed value.
897
 * \return
898
 *      Number of bytes written to `out`.
899
 */
900
static inline size_t
901
sint64_pack(int64_t value, uint8_t *out)
902
0
{
903
0
  return uint64_pack(zigzag64(value), out);
904
0
}
905
906
/**
907
 * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
908
 * types fixed32, sfixed32, float. Similar to "htole32".
909
 *
910
 * \param value
911
 *      Value to encode.
912
 * \param[out] out
913
 *      Packed value.
914
 * \return
915
 *      Number of bytes written to `out`.
916
 */
917
static inline size_t
918
fixed32_pack(uint32_t value, void *out)
919
0
{
920
0
#if !defined(WORDS_BIGENDIAN)
921
0
  memcpy(out, &value, 4);
922
#else
923
  uint8_t *buf = out;
924
925
  buf[0] = value;
926
  buf[1] = value >> 8;
927
  buf[2] = value >> 16;
928
  buf[3] = value >> 24;
929
#endif
930
0
  return 4;
931
0
}
932
933
/**
934
 * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
935
 * types fixed64, sfixed64, double. Similar to "htole64".
936
 *
937
 * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
938
 * version would be appreciated, plus a way to decide to use 64-bit math where
939
 * convenient.
940
 *
941
 * \param value
942
 *      Value to encode.
943
 * \param[out] out
944
 *      Packed value.
945
 * \return
946
 *      Number of bytes written to `out`.
947
 */
948
static inline size_t
949
fixed64_pack(uint64_t value, void *out)
950
0
{
951
0
#if !defined(WORDS_BIGENDIAN)
952
0
  memcpy(out, &value, 8);
953
#else
954
  fixed32_pack(value, out);
955
  fixed32_pack(value >> 32, ((char *) out) + 4);
956
#endif
957
0
  return 8;
958
0
}
959
960
/**
961
 * Pack a boolean value as an integer and return the number of bytes written.
962
 *
963
 * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
964
 * that is idiomatic C++ in some STL implementations.
965
 *
966
 * \param value
967
 *      Value to encode.
968
 * \param[out] out
969
 *      Packed value.
970
 * \return
971
 *      Number of bytes written to `out`.
972
 */
973
static inline size_t
974
boolean_pack(protobuf_c_boolean value, uint8_t *out)
975
0
{
976
0
  *out = value ? TRUE : FALSE;
977
0
  return 1;
978
0
}
979
980
/**
981
 * Pack a NUL-terminated C string and return the number of bytes written. The
982
 * output includes a length delimiter.
983
 *
984
 * The NULL pointer is treated as an empty string. This isn't really necessary,
985
 * but it allows people to leave required strings blank. (See Issue #13 in the
986
 * bug tracker for a little more explanation).
987
 *
988
 * \param str
989
 *      String to encode.
990
 * \param[out] out
991
 *      Packed value.
992
 * \return
993
 *      Number of bytes written to `out`.
994
 */
995
static inline size_t
996
string_pack(const char *str, uint8_t *out)
997
0
{
998
0
  if (str == NULL) {
999
0
    out[0] = 0;
1000
0
    return 1;
1001
0
  } else {
1002
0
    size_t len = strlen(str);
1003
0
    size_t rv = uint32_pack(len, out);
1004
0
    memcpy(out + rv, str, len);
1005
0
    return rv + len;
1006
0
  }
1007
0
}
1008
1009
/**
1010
 * Pack a ProtobufCBinaryData and return the number of bytes written. The output
1011
 * includes a length delimiter.
1012
 *
1013
 * \param bd
1014
 *      ProtobufCBinaryData to encode.
1015
 * \param[out] out
1016
 *      Packed value.
1017
 * \return
1018
 *      Number of bytes written to `out`.
1019
 */
1020
static inline size_t
1021
binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
1022
0
{
1023
0
  size_t len = bd->len;
1024
0
  size_t rv = uint32_pack(len, out);
1025
0
  memcpy(out + rv, bd->data, len);
1026
0
  return rv + len;
1027
0
}
1028
1029
/**
1030
 * Pack a ProtobufCMessage and return the number of bytes written. The output
1031
 * includes a length delimiter.
1032
 *
1033
 * \param message
1034
 *      ProtobufCMessage object to pack.
1035
 * \param[out] out
1036
 *      Packed message.
1037
 * \return
1038
 *      Number of bytes written to `out`.
1039
 */
1040
static inline size_t
1041
prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
1042
0
{
1043
0
  if (message == NULL) {
1044
0
    out[0] = 0;
1045
0
    return 1;
1046
0
  } else {
1047
0
    size_t rv = protobuf_c_message_pack(message, out + 1);
1048
0
    uint32_t rv_packed_size = uint32_size(rv);
1049
0
    if (rv_packed_size != 1)
1050
0
      memmove(out + rv_packed_size, out + 1, rv);
1051
0
    return uint32_pack(rv, out) + rv;
1052
0
  }
1053
0
}
1054
1055
/**
1056
 * Pack a field tag.
1057
 *
1058
 * Wire-type will be added in required_field_pack().
1059
 *
1060
 * \todo Just call uint64_pack on 64-bit platforms.
1061
 *
1062
 * \param id
1063
 *      Tag value to encode.
1064
 * \param[out] out
1065
 *      Packed value.
1066
 * \return
1067
 *      Number of bytes written to `out`.
1068
 */
1069
static size_t
1070
tag_pack(uint32_t id, uint8_t *out)
1071
0
{
1072
0
  if (id < (1UL << (32 - 3)))
1073
0
    return uint32_pack(id << 3, out);
1074
0
  else
1075
0
    return uint64_pack(((uint64_t) id) << 3, out);
1076
0
}
1077
1078
/**
1079
 * Pack a required field and return the number of bytes written.
1080
 *
1081
 * \param field
1082
 *      Field descriptor.
1083
 * \param member
1084
 *      The field member.
1085
 * \param[out] out
1086
 *      Packed value.
1087
 * \return
1088
 *      Number of bytes written to `out`.
1089
 */
1090
static size_t
1091
required_field_pack(const ProtobufCFieldDescriptor *field,
1092
        const void *member, uint8_t *out)
1093
0
{
1094
0
  size_t rv = tag_pack(field->id, out);
1095
1096
0
  switch (field->type) {
1097
0
  case PROTOBUF_C_TYPE_SINT32:
1098
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1099
0
    return rv + sint32_pack(*(const int32_t *) member, out + rv);
1100
0
  case PROTOBUF_C_TYPE_ENUM:
1101
0
  case PROTOBUF_C_TYPE_INT32:
1102
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1103
0
    return rv + int32_pack(*(const int32_t *) member, out + rv);
1104
0
  case PROTOBUF_C_TYPE_UINT32:
1105
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1106
0
    return rv + uint32_pack(*(const uint32_t *) member, out + rv);
1107
0
  case PROTOBUF_C_TYPE_SINT64:
1108
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1109
0
    return rv + sint64_pack(*(const int64_t *) member, out + rv);
1110
0
  case PROTOBUF_C_TYPE_INT64:
1111
0
  case PROTOBUF_C_TYPE_UINT64:
1112
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1113
0
    return rv + uint64_pack(*(const uint64_t *) member, out + rv);
1114
0
  case PROTOBUF_C_TYPE_SFIXED32:
1115
0
  case PROTOBUF_C_TYPE_FIXED32:
1116
0
  case PROTOBUF_C_TYPE_FLOAT:
1117
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1118
0
    return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
1119
0
  case PROTOBUF_C_TYPE_SFIXED64:
1120
0
  case PROTOBUF_C_TYPE_FIXED64:
1121
0
  case PROTOBUF_C_TYPE_DOUBLE:
1122
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1123
0
    return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
1124
0
  case PROTOBUF_C_TYPE_BOOL:
1125
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1126
0
    return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
1127
0
  case PROTOBUF_C_TYPE_STRING:
1128
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1129
0
    return rv + string_pack(*(char *const *) member, out + rv);
1130
0
  case PROTOBUF_C_TYPE_BYTES:
1131
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1132
0
    return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
1133
0
  case PROTOBUF_C_TYPE_MESSAGE:
1134
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1135
0
    return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
1136
0
  }
1137
0
  PROTOBUF_C__ASSERT_NOT_REACHED();
1138
0
  return 0;
1139
0
}
1140
1141
/**
1142
 * Pack a oneof field and return the number of bytes written. Only packs the
1143
 * field that is selected by the case enum.
1144
 *
1145
 * \param field
1146
 *      Field descriptor.
1147
 * \param oneof_case
1148
 *      Enum value that selects the field in the oneof.
1149
 * \param member
1150
 *      The field member.
1151
 * \param[out] out
1152
 *      Packed value.
1153
 * \return
1154
 *      Number of bytes written to `out`.
1155
 */
1156
static size_t
1157
oneof_field_pack(const ProtobufCFieldDescriptor *field,
1158
     uint32_t oneof_case,
1159
     const void *member, uint8_t *out)
1160
0
{
1161
0
  if (oneof_case != field->id) {
1162
0
    return 0;
1163
0
  }
1164
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1165
0
      field->type == PROTOBUF_C_TYPE_STRING)
1166
0
  {
1167
0
    const void *ptr = *(const void * const *) member;
1168
0
    if (ptr == NULL || ptr == field->default_value)
1169
0
      return 0;
1170
0
  }
1171
0
  return required_field_pack(field, member, out);
1172
0
}
1173
1174
/**
1175
 * Pack an optional field and return the number of bytes written.
1176
 *
1177
 * \param field
1178
 *      Field descriptor.
1179
 * \param has
1180
 *      Whether the field is set.
1181
 * \param member
1182
 *      The field member.
1183
 * \param[out] out
1184
 *      Packed value.
1185
 * \return
1186
 *      Number of bytes written to `out`.
1187
 */
1188
static size_t
1189
optional_field_pack(const ProtobufCFieldDescriptor *field,
1190
        const protobuf_c_boolean has,
1191
        const void *member, uint8_t *out)
1192
0
{
1193
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1194
0
      field->type == PROTOBUF_C_TYPE_STRING)
1195
0
  {
1196
0
    const void *ptr = *(const void * const *) member;
1197
0
    if (ptr == NULL || ptr == field->default_value)
1198
0
      return 0;
1199
0
  } else {
1200
0
    if (!has)
1201
0
      return 0;
1202
0
  }
1203
0
  return required_field_pack(field, member, out);
1204
0
}
1205
1206
/**
1207
 * Pack an unlabeled field and return the number of bytes written.
1208
 *
1209
 * \param field
1210
 *      Field descriptor.
1211
 * \param member
1212
 *      The field member.
1213
 * \param[out] out
1214
 *      Packed value.
1215
 * \return
1216
 *      Number of bytes written to `out`.
1217
 */
1218
static size_t
1219
unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
1220
         const void *member, uint8_t *out)
1221
0
{
1222
0
  if (field_is_zeroish(field, member))
1223
0
    return 0;
1224
0
  return required_field_pack(field, member, out);
1225
0
}
1226
1227
/**
1228
 * Given a field type, return the in-memory size.
1229
 *
1230
 * \todo Implement as a table lookup.
1231
 *
1232
 * \param type
1233
 *      Field type.
1234
 * \return
1235
 *      Size of the field.
1236
 */
1237
static inline size_t
1238
sizeof_elt_in_repeated_array(ProtobufCType type)
1239
0
{
1240
0
  switch (type) {
1241
0
  case PROTOBUF_C_TYPE_SINT32:
1242
0
  case PROTOBUF_C_TYPE_INT32:
1243
0
  case PROTOBUF_C_TYPE_UINT32:
1244
0
  case PROTOBUF_C_TYPE_SFIXED32:
1245
0
  case PROTOBUF_C_TYPE_FIXED32:
1246
0
  case PROTOBUF_C_TYPE_FLOAT:
1247
0
  case PROTOBUF_C_TYPE_ENUM:
1248
0
    return 4;
1249
0
  case PROTOBUF_C_TYPE_SINT64:
1250
0
  case PROTOBUF_C_TYPE_INT64:
1251
0
  case PROTOBUF_C_TYPE_UINT64:
1252
0
  case PROTOBUF_C_TYPE_SFIXED64:
1253
0
  case PROTOBUF_C_TYPE_FIXED64:
1254
0
  case PROTOBUF_C_TYPE_DOUBLE:
1255
0
    return 8;
1256
0
  case PROTOBUF_C_TYPE_BOOL:
1257
0
    return sizeof(protobuf_c_boolean);
1258
0
  case PROTOBUF_C_TYPE_STRING:
1259
0
  case PROTOBUF_C_TYPE_MESSAGE:
1260
0
    return sizeof(void *);
1261
0
  case PROTOBUF_C_TYPE_BYTES:
1262
0
    return sizeof(ProtobufCBinaryData);
1263
0
  }
1264
0
  PROTOBUF_C__ASSERT_NOT_REACHED();
1265
0
  return 0;
1266
0
}
1267
1268
/**
1269
 * Pack an array of 32-bit quantities.
1270
 *
1271
 * \param[out] out
1272
 *      Destination.
1273
 * \param[in] in
1274
 *      Source.
1275
 * \param[in] n
1276
 *      Number of elements in the source array.
1277
 */
1278
static void
1279
copy_to_little_endian_32(void *out, const void *in, const unsigned n)
1280
0
{
1281
0
#if !defined(WORDS_BIGENDIAN)
1282
0
  memcpy(out, in, n * 4);
1283
#else
1284
  unsigned i;
1285
  const uint32_t *ini = in;
1286
  for (i = 0; i < n; i++)
1287
    fixed32_pack(ini[i], (uint32_t *) out + i);
1288
#endif
1289
0
}
1290
1291
/**
1292
 * Pack an array of 64-bit quantities.
1293
 *
1294
 * \param[out] out
1295
 *      Destination.
1296
 * \param[in] in
1297
 *      Source.
1298
 * \param[in] n
1299
 *      Number of elements in the source array.
1300
 */
1301
static void
1302
copy_to_little_endian_64(void *out, const void *in, const unsigned n)
1303
0
{
1304
0
#if !defined(WORDS_BIGENDIAN)
1305
0
  memcpy(out, in, n * 8);
1306
#else
1307
  unsigned i;
1308
  const uint64_t *ini = in;
1309
  for (i = 0; i < n; i++)
1310
    fixed64_pack(ini[i], (uint64_t *) out + i);
1311
#endif
1312
0
}
1313
1314
/**
1315
 * Get the minimum number of bytes required to pack a field value of a
1316
 * particular type.
1317
 *
1318
 * \param type
1319
 *      Field type.
1320
 * \return
1321
 *      Number of bytes.
1322
 */
1323
static unsigned
1324
get_type_min_size(ProtobufCType type)
1325
0
{
1326
0
  if (type == PROTOBUF_C_TYPE_SFIXED32 ||
1327
0
      type == PROTOBUF_C_TYPE_FIXED32 ||
1328
0
      type == PROTOBUF_C_TYPE_FLOAT)
1329
0
  {
1330
0
    return 4;
1331
0
  }
1332
0
  if (type == PROTOBUF_C_TYPE_SFIXED64 ||
1333
0
      type == PROTOBUF_C_TYPE_FIXED64 ||
1334
0
      type == PROTOBUF_C_TYPE_DOUBLE)
1335
0
  {
1336
0
    return 8;
1337
0
  }
1338
0
  return 1;
1339
0
}
1340
1341
/**
1342
 * Packs the elements of a repeated field and returns the serialised field and
1343
 * its length.
1344
 *
1345
 * \param field
1346
 *      Field descriptor.
1347
 * \param count
1348
 *      Number of elements in the repeated field array.
1349
 * \param member
1350
 *      Pointer to the elements for this repeated field.
1351
 * \param[out] out
1352
 *      Serialised representation of the repeated field.
1353
 * \return
1354
 *      Number of bytes serialised to `out`.
1355
 */
1356
static size_t
1357
repeated_field_pack(const ProtobufCFieldDescriptor *field,
1358
        size_t count, const void *member, uint8_t *out)
1359
0
{
1360
0
  void *array = *(void * const *) member;
1361
0
  unsigned i;
1362
1363
0
  if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1364
0
    unsigned header_len;
1365
0
    unsigned len_start;
1366
0
    unsigned min_length;
1367
0
    unsigned payload_len;
1368
0
    unsigned length_size_min;
1369
0
    unsigned actual_length_size;
1370
0
    uint8_t *payload_at;
1371
1372
0
    if (count == 0)
1373
0
      return 0;
1374
0
    header_len = tag_pack(field->id, out);
1375
0
    out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1376
0
    len_start = header_len;
1377
0
    min_length = get_type_min_size(field->type) * count;
1378
0
    length_size_min = uint32_size(min_length);
1379
0
    header_len += length_size_min;
1380
0
    payload_at = out + header_len;
1381
1382
0
    switch (field->type) {
1383
0
    case PROTOBUF_C_TYPE_SFIXED32:
1384
0
    case PROTOBUF_C_TYPE_FIXED32:
1385
0
    case PROTOBUF_C_TYPE_FLOAT:
1386
0
      copy_to_little_endian_32(payload_at, array, count);
1387
0
      payload_at += count * 4;
1388
0
      break;
1389
0
    case PROTOBUF_C_TYPE_SFIXED64:
1390
0
    case PROTOBUF_C_TYPE_FIXED64:
1391
0
    case PROTOBUF_C_TYPE_DOUBLE:
1392
0
      copy_to_little_endian_64(payload_at, array, count);
1393
0
      payload_at += count * 8;
1394
0
      break;
1395
0
    case PROTOBUF_C_TYPE_ENUM:
1396
0
    case PROTOBUF_C_TYPE_INT32: {
1397
0
      const int32_t *arr = (const int32_t *) array;
1398
0
      for (i = 0; i < count; i++)
1399
0
        payload_at += int32_pack(arr[i], payload_at);
1400
0
      break;
1401
0
    }
1402
0
    case PROTOBUF_C_TYPE_SINT32: {
1403
0
      const int32_t *arr = (const int32_t *) array;
1404
0
      for (i = 0; i < count; i++)
1405
0
        payload_at += sint32_pack(arr[i], payload_at);
1406
0
      break;
1407
0
    }
1408
0
    case PROTOBUF_C_TYPE_SINT64: {
1409
0
      const int64_t *arr = (const int64_t *) array;
1410
0
      for (i = 0; i < count; i++)
1411
0
        payload_at += sint64_pack(arr[i], payload_at);
1412
0
      break;
1413
0
    }
1414
0
    case PROTOBUF_C_TYPE_UINT32: {
1415
0
      const uint32_t *arr = (const uint32_t *) array;
1416
0
      for (i = 0; i < count; i++)
1417
0
        payload_at += uint32_pack(arr[i], payload_at);
1418
0
      break;
1419
0
    }
1420
0
    case PROTOBUF_C_TYPE_INT64:
1421
0
    case PROTOBUF_C_TYPE_UINT64: {
1422
0
      const uint64_t *arr = (const uint64_t *) array;
1423
0
      for (i = 0; i < count; i++)
1424
0
        payload_at += uint64_pack(arr[i], payload_at);
1425
0
      break;
1426
0
    }
1427
0
    case PROTOBUF_C_TYPE_BOOL: {
1428
0
      const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
1429
0
      for (i = 0; i < count; i++)
1430
0
        payload_at += boolean_pack(arr[i], payload_at);
1431
0
      break;
1432
0
    }
1433
0
    default:
1434
0
      PROTOBUF_C__ASSERT_NOT_REACHED();
1435
0
    }
1436
1437
0
    payload_len = payload_at - (out + header_len);
1438
0
    actual_length_size = uint32_size(payload_len);
1439
0
    if (length_size_min != actual_length_size) {
1440
0
      assert(actual_length_size == length_size_min + 1);
1441
0
      memmove(out + header_len + 1, out + header_len,
1442
0
        payload_len);
1443
0
      header_len++;
1444
0
    }
1445
0
    uint32_pack(payload_len, out + len_start);
1446
0
    return header_len + payload_len;
1447
0
  } else {
1448
    /* not "packed" cased */
1449
    /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1450
0
    size_t rv = 0;
1451
0
    unsigned siz = sizeof_elt_in_repeated_array(field->type);
1452
1453
0
    for (i = 0; i < count; i++) {
1454
0
      rv += required_field_pack(field, array, out + rv);
1455
0
      array = (char *)array + siz;
1456
0
    }
1457
0
    return rv;
1458
0
  }
1459
0
}
1460
1461
static size_t
1462
unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
1463
0
{
1464
0
  size_t rv = tag_pack(field->tag, out);
1465
0
  out[0] |= field->wire_type;
1466
0
  memcpy(out + rv, field->data, field->len);
1467
0
  return rv + field->len;
1468
0
}
1469
1470
/**@}*/
1471
1472
size_t
1473
protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
1474
0
{
1475
0
  unsigned i;
1476
0
  size_t rv = 0;
1477
1478
0
  ASSERT_IS_MESSAGE(message);
1479
0
  for (i = 0; i < message->descriptor->n_fields; i++) {
1480
0
    const ProtobufCFieldDescriptor *field =
1481
0
      message->descriptor->fields + i;
1482
0
    const void *member = ((const char *) message) + field->offset;
1483
1484
    /*
1485
     * It doesn't hurt to compute qmember (a pointer to the
1486
     * quantifier field of the structure), but the pointer is only
1487
     * valid if the field is:
1488
     *  - a repeated field, or
1489
     *  - a field that is part of a oneof
1490
     *  - an optional field that isn't a pointer type
1491
     * (Meaning: not a message or a string).
1492
     */
1493
0
    const void *qmember =
1494
0
      ((const char *) message) + field->quantifier_offset;
1495
1496
0
    if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1497
0
      rv += required_field_pack(field, member, out + rv);
1498
0
    } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1499
0
          field->label == PROTOBUF_C_LABEL_NONE) &&
1500
0
         (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1501
0
      rv += oneof_field_pack(
1502
0
        field,
1503
0
        *(const uint32_t *) qmember,
1504
0
        member,
1505
0
        out + rv
1506
0
      );
1507
0
    } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1508
0
      rv += optional_field_pack(
1509
0
        field,
1510
0
        *(const protobuf_c_boolean *) qmember,
1511
0
        member,
1512
0
        out + rv
1513
0
      );
1514
0
    } else if (field->label == PROTOBUF_C_LABEL_NONE) {
1515
0
      rv += unlabeled_field_pack(field, member, out + rv);
1516
0
    } else {
1517
0
      rv += repeated_field_pack(field, *(const size_t *) qmember,
1518
0
        member, out + rv);
1519
0
    }
1520
0
  }
1521
0
  for (i = 0; i < message->n_unknown_fields; i++)
1522
0
    rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
1523
0
  return rv;
1524
0
}
1525
1526
/**
1527
 * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
1528
 *
1529
 * Routines mainly used by protobuf_c_message_pack_to_buffer().
1530
 *
1531
 * \ingroup internal
1532
 * @{
1533
 */
1534
1535
/**
1536
 * Pack a required field to a virtual buffer.
1537
 *
1538
 * \param field
1539
 *      Field descriptor.
1540
 * \param member
1541
 *      The element to be packed.
1542
 * \param[out] buffer
1543
 *      Virtual buffer to append data to.
1544
 * \return
1545
 *      Number of bytes packed.
1546
 */
1547
static size_t
1548
required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1549
            const void *member, ProtobufCBuffer *buffer)
1550
0
{
1551
0
  size_t rv;
1552
0
  uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1553
1554
0
  rv = tag_pack(field->id, scratch);
1555
0
  switch (field->type) {
1556
0
  case PROTOBUF_C_TYPE_SINT32:
1557
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1558
0
    rv += sint32_pack(*(const int32_t *) member, scratch + rv);
1559
0
    buffer->append(buffer, rv, scratch);
1560
0
    break;
1561
0
  case PROTOBUF_C_TYPE_ENUM:
1562
0
  case PROTOBUF_C_TYPE_INT32:
1563
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1564
0
    rv += int32_pack(*(const int32_t *) member, scratch + rv);
1565
0
    buffer->append(buffer, rv, scratch);
1566
0
    break;
1567
0
  case PROTOBUF_C_TYPE_UINT32:
1568
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1569
0
    rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
1570
0
    buffer->append(buffer, rv, scratch);
1571
0
    break;
1572
0
  case PROTOBUF_C_TYPE_SINT64:
1573
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1574
0
    rv += sint64_pack(*(const int64_t *) member, scratch + rv);
1575
0
    buffer->append(buffer, rv, scratch);
1576
0
    break;
1577
0
  case PROTOBUF_C_TYPE_INT64:
1578
0
  case PROTOBUF_C_TYPE_UINT64:
1579
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1580
0
    rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
1581
0
    buffer->append(buffer, rv, scratch);
1582
0
    break;
1583
0
  case PROTOBUF_C_TYPE_SFIXED32:
1584
0
  case PROTOBUF_C_TYPE_FIXED32:
1585
0
  case PROTOBUF_C_TYPE_FLOAT:
1586
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
1587
0
    rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
1588
0
    buffer->append(buffer, rv, scratch);
1589
0
    break;
1590
0
  case PROTOBUF_C_TYPE_SFIXED64:
1591
0
  case PROTOBUF_C_TYPE_FIXED64:
1592
0
  case PROTOBUF_C_TYPE_DOUBLE:
1593
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
1594
0
    rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
1595
0
    buffer->append(buffer, rv, scratch);
1596
0
    break;
1597
0
  case PROTOBUF_C_TYPE_BOOL:
1598
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
1599
0
    rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
1600
0
    buffer->append(buffer, rv, scratch);
1601
0
    break;
1602
0
  case PROTOBUF_C_TYPE_STRING: {
1603
0
    const char *str = *(char *const *) member;
1604
0
    size_t sublen = str ? strlen(str) : 0;
1605
1606
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1607
0
    rv += uint32_pack(sublen, scratch + rv);
1608
0
    buffer->append(buffer, rv, scratch);
1609
0
    buffer->append(buffer, sublen, (const uint8_t *) str);
1610
0
    rv += sublen;
1611
0
    break;
1612
0
  }
1613
0
  case PROTOBUF_C_TYPE_BYTES: {
1614
0
    const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
1615
0
    size_t sublen = bd->len;
1616
1617
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1618
0
    rv += uint32_pack(sublen, scratch + rv);
1619
0
    buffer->append(buffer, rv, scratch);
1620
0
    buffer->append(buffer, sublen, bd->data);
1621
0
    rv += sublen;
1622
0
    break;
1623
0
  }
1624
0
  case PROTOBUF_C_TYPE_MESSAGE: {
1625
0
    const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
1626
    
1627
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1628
0
    if (msg == NULL) {
1629
0
      rv += uint32_pack(0, scratch + rv);
1630
0
      buffer->append(buffer, rv, scratch);
1631
0
    } else {
1632
0
      size_t sublen = protobuf_c_message_get_packed_size(msg);
1633
0
      rv += uint32_pack(sublen, scratch + rv);
1634
0
      buffer->append(buffer, rv, scratch);
1635
0
      protobuf_c_message_pack_to_buffer(msg, buffer);
1636
0
      rv += sublen;
1637
0
    }
1638
0
    break;
1639
0
  }
1640
0
  default:
1641
0
    PROTOBUF_C__ASSERT_NOT_REACHED();
1642
0
  }
1643
0
  return rv;
1644
0
}
1645
1646
/**
1647
 * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
1648
 *
1649
 * \param field
1650
 *      Field descriptor.
1651
 * \param oneof_case
1652
 *      Enum value that selects the field in the oneof.
1653
 * \param member
1654
 *      The element to be packed.
1655
 * \param[out] buffer
1656
 *      Virtual buffer to append data to.
1657
 * \return
1658
 *      Number of bytes serialised to `buffer`.
1659
 */
1660
static size_t
1661
oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1662
         uint32_t oneof_case,
1663
         const void *member, ProtobufCBuffer *buffer)
1664
0
{
1665
0
  if (oneof_case != field->id) {
1666
0
    return 0;
1667
0
  }
1668
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1669
0
      field->type == PROTOBUF_C_TYPE_STRING)
1670
0
  {
1671
0
    const void *ptr = *(const void *const *) member;
1672
0
    if (ptr == NULL || ptr == field->default_value)
1673
0
      return 0;
1674
0
  }
1675
0
  return required_field_pack_to_buffer(field, member, buffer);
1676
0
}
1677
1678
/**
1679
 * Pack an optional field to a buffer.
1680
 *
1681
 * \param field
1682
 *      Field descriptor.
1683
 * \param has
1684
 *      Whether the field is set.
1685
 * \param member
1686
 *      The element to be packed.
1687
 * \param[out] buffer
1688
 *      Virtual buffer to append data to.
1689
 * \return
1690
 *      Number of bytes serialised to `buffer`.
1691
 */
1692
static size_t
1693
optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1694
            const protobuf_c_boolean has,
1695
            const void *member, ProtobufCBuffer *buffer)
1696
0
{
1697
0
  if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
1698
0
      field->type == PROTOBUF_C_TYPE_STRING)
1699
0
  {
1700
0
    const void *ptr = *(const void *const *) member;
1701
0
    if (ptr == NULL || ptr == field->default_value)
1702
0
      return 0;
1703
0
  } else {
1704
0
    if (!has)
1705
0
      return 0;
1706
0
  }
1707
0
  return required_field_pack_to_buffer(field, member, buffer);
1708
0
}
1709
1710
/**
1711
 * Pack an unlabeled field to a buffer.
1712
 *
1713
 * \param field
1714
 *      Field descriptor.
1715
 * \param member
1716
 *      The element to be packed.
1717
 * \param[out] buffer
1718
 *      Virtual buffer to append data to.
1719
 * \return
1720
 *      Number of bytes serialised to `buffer`.
1721
 */
1722
static size_t
1723
unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1724
             const void *member, ProtobufCBuffer *buffer)
1725
0
{
1726
0
  if (field_is_zeroish(field, member))
1727
0
    return 0;
1728
0
  return required_field_pack_to_buffer(field, member, buffer);
1729
0
}
1730
1731
/**
1732
 * Get the packed size of an array of same field type.
1733
 *
1734
 * \param field
1735
 *      Field descriptor.
1736
 * \param count
1737
 *      Number of elements of this type.
1738
 * \param array
1739
 *      The elements to get the size of.
1740
 * \return
1741
 *      Number of bytes required.
1742
 */
1743
static size_t
1744
get_packed_payload_length(const ProtobufCFieldDescriptor *field,
1745
        unsigned count, const void *array)
1746
0
{
1747
0
  unsigned rv = 0;
1748
0
  unsigned i;
1749
1750
0
  switch (field->type) {
1751
0
  case PROTOBUF_C_TYPE_SFIXED32:
1752
0
  case PROTOBUF_C_TYPE_FIXED32:
1753
0
  case PROTOBUF_C_TYPE_FLOAT:
1754
0
    return count * 4;
1755
0
  case PROTOBUF_C_TYPE_SFIXED64:
1756
0
  case PROTOBUF_C_TYPE_FIXED64:
1757
0
  case PROTOBUF_C_TYPE_DOUBLE:
1758
0
    return count * 8;
1759
0
  case PROTOBUF_C_TYPE_ENUM:
1760
0
  case PROTOBUF_C_TYPE_INT32: {
1761
0
    const int32_t *arr = (const int32_t *) array;
1762
0
    for (i = 0; i < count; i++)
1763
0
      rv += int32_size(arr[i]);
1764
0
    break;
1765
0
  }
1766
0
  case PROTOBUF_C_TYPE_SINT32: {
1767
0
    const int32_t *arr = (const int32_t *) array;
1768
0
    for (i = 0; i < count; i++)
1769
0
      rv += sint32_size(arr[i]);
1770
0
    break;
1771
0
  }
1772
0
  case PROTOBUF_C_TYPE_UINT32: {
1773
0
    const uint32_t *arr = (const uint32_t *) array;
1774
0
    for (i = 0; i < count; i++)
1775
0
      rv += uint32_size(arr[i]);
1776
0
    break;
1777
0
  }
1778
0
  case PROTOBUF_C_TYPE_SINT64: {
1779
0
    const int64_t *arr = (const int64_t *) array;
1780
0
    for (i = 0; i < count; i++)
1781
0
      rv += sint64_size(arr[i]);
1782
0
    break;
1783
0
  }
1784
0
  case PROTOBUF_C_TYPE_INT64:
1785
0
  case PROTOBUF_C_TYPE_UINT64: {
1786
0
    const uint64_t *arr = (const uint64_t *) array;
1787
0
    for (i = 0; i < count; i++)
1788
0
      rv += uint64_size(arr[i]);
1789
0
    break;
1790
0
  }
1791
0
  case PROTOBUF_C_TYPE_BOOL:
1792
0
    return count;
1793
0
  default:
1794
0
    PROTOBUF_C__ASSERT_NOT_REACHED();
1795
0
  }
1796
0
  return rv;
1797
0
}
1798
1799
/**
1800
 * Pack an array of same field type to a virtual buffer.
1801
 *
1802
 * \param field
1803
 *      Field descriptor.
1804
 * \param count
1805
 *      Number of elements of this type.
1806
 * \param array
1807
 *      The elements to get the size of.
1808
 * \param[out] buffer
1809
 *      Virtual buffer to append data to.
1810
 * \return
1811
 *      Number of bytes packed.
1812
 */
1813
static size_t
1814
pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
1815
         unsigned count, const void *array,
1816
         ProtobufCBuffer *buffer)
1817
0
{
1818
0
  uint8_t scratch[16];
1819
0
  size_t rv = 0;
1820
0
  unsigned i;
1821
1822
0
  switch (field->type) {
1823
0
  case PROTOBUF_C_TYPE_SFIXED32:
1824
0
  case PROTOBUF_C_TYPE_FIXED32:
1825
0
  case PROTOBUF_C_TYPE_FLOAT:
1826
0
#if !defined(WORDS_BIGENDIAN)
1827
0
    rv = count * 4;
1828
0
    goto no_packing_needed;
1829
#else
1830
    for (i = 0; i < count; i++) {
1831
      unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
1832
      buffer->append(buffer, len, scratch);
1833
      rv += len;
1834
    }
1835
    break;
1836
#endif
1837
0
  case PROTOBUF_C_TYPE_SFIXED64:
1838
0
  case PROTOBUF_C_TYPE_FIXED64:
1839
0
  case PROTOBUF_C_TYPE_DOUBLE:
1840
0
#if !defined(WORDS_BIGENDIAN)
1841
0
    rv = count * 8;
1842
0
    goto no_packing_needed;
1843
#else
1844
    for (i = 0; i < count; i++) {
1845
      unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
1846
      buffer->append(buffer, len, scratch);
1847
      rv += len;
1848
    }
1849
    break;
1850
#endif
1851
0
  case PROTOBUF_C_TYPE_ENUM:
1852
0
  case PROTOBUF_C_TYPE_INT32:
1853
0
    for (i = 0; i < count; i++) {
1854
0
      unsigned len = int32_pack(((int32_t *) array)[i], scratch);
1855
0
      buffer->append(buffer, len, scratch);
1856
0
      rv += len;
1857
0
    }
1858
0
    break;
1859
0
  case PROTOBUF_C_TYPE_SINT32:
1860
0
    for (i = 0; i < count; i++) {
1861
0
      unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
1862
0
      buffer->append(buffer, len, scratch);
1863
0
      rv += len;
1864
0
    }
1865
0
    break;
1866
0
  case PROTOBUF_C_TYPE_UINT32:
1867
0
    for (i = 0; i < count; i++) {
1868
0
      unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
1869
0
      buffer->append(buffer, len, scratch);
1870
0
      rv += len;
1871
0
    }
1872
0
    break;
1873
0
  case PROTOBUF_C_TYPE_SINT64:
1874
0
    for (i = 0; i < count; i++) {
1875
0
      unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
1876
0
      buffer->append(buffer, len, scratch);
1877
0
      rv += len;
1878
0
    }
1879
0
    break;
1880
0
  case PROTOBUF_C_TYPE_INT64:
1881
0
  case PROTOBUF_C_TYPE_UINT64:
1882
0
    for (i = 0; i < count; i++) {
1883
0
      unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
1884
0
      buffer->append(buffer, len, scratch);
1885
0
      rv += len;
1886
0
    }
1887
0
    break;
1888
0
  case PROTOBUF_C_TYPE_BOOL:
1889
0
    for (i = 0; i < count; i++) {
1890
0
      unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
1891
0
      buffer->append(buffer, len, scratch);
1892
0
      rv += len;
1893
0
    }
1894
0
    return count;
1895
0
  default:
1896
0
    PROTOBUF_C__ASSERT_NOT_REACHED();
1897
0
  }
1898
0
  return rv;
1899
1900
0
#if !defined(WORDS_BIGENDIAN)
1901
0
no_packing_needed:
1902
0
  buffer->append(buffer, rv, array);
1903
0
  return rv;
1904
0
#endif
1905
0
}
1906
1907
static size_t
1908
repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
1909
            unsigned count, const void *member,
1910
            ProtobufCBuffer *buffer)
1911
0
{
1912
0
  char *array = *(char * const *) member;
1913
1914
0
  if (count == 0)
1915
0
    return 0;
1916
0
  if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
1917
0
    uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
1918
0
    size_t rv = tag_pack(field->id, scratch);
1919
0
    size_t payload_len = get_packed_payload_length(field, count, array);
1920
0
    size_t tmp;
1921
1922
0
    scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
1923
0
    rv += uint32_pack(payload_len, scratch + rv);
1924
0
    buffer->append(buffer, rv, scratch);
1925
0
    tmp = pack_buffer_packed_payload(field, count, array, buffer);
1926
0
    assert(tmp == payload_len);
1927
0
    return rv + payload_len;
1928
0
  } else {
1929
0
    size_t siz;
1930
0
    unsigned i;
1931
    /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
1932
0
    unsigned rv = 0;
1933
1934
0
    siz = sizeof_elt_in_repeated_array(field->type);
1935
0
    for (i = 0; i < count; i++) {
1936
0
      rv += required_field_pack_to_buffer(field, array, buffer);
1937
0
      array += siz;
1938
0
    }
1939
0
    return rv;
1940
0
  }
1941
0
}
1942
1943
static size_t
1944
unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
1945
           ProtobufCBuffer *buffer)
1946
0
{
1947
0
  uint8_t header[MAX_UINT64_ENCODED_SIZE];
1948
0
  size_t rv = tag_pack(field->tag, header);
1949
1950
0
  header[0] |= field->wire_type;
1951
0
  buffer->append(buffer, rv, header);
1952
0
  buffer->append(buffer, field->len, field->data);
1953
0
  return rv + field->len;
1954
0
}
1955
1956
/**@}*/
1957
1958
size_t
1959
protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
1960
          ProtobufCBuffer *buffer)
1961
0
{
1962
0
  unsigned i;
1963
0
  size_t rv = 0;
1964
1965
0
  ASSERT_IS_MESSAGE(message);
1966
0
  for (i = 0; i < message->descriptor->n_fields; i++) {
1967
0
    const ProtobufCFieldDescriptor *field =
1968
0
      message->descriptor->fields + i;
1969
0
    const void *member =
1970
0
      ((const char *) message) + field->offset;
1971
0
    const void *qmember =
1972
0
      ((const char *) message) + field->quantifier_offset;
1973
1974
0
    if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
1975
0
      rv += required_field_pack_to_buffer(field, member, buffer);
1976
0
    } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
1977
0
          field->label == PROTOBUF_C_LABEL_NONE) &&
1978
0
         (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
1979
0
      rv += oneof_field_pack_to_buffer(
1980
0
        field,
1981
0
        *(const uint32_t *) qmember,
1982
0
        member,
1983
0
        buffer
1984
0
      );
1985
0
    } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
1986
0
      rv += optional_field_pack_to_buffer(
1987
0
        field,
1988
0
        *(const protobuf_c_boolean *) qmember,
1989
0
        member,
1990
0
        buffer
1991
0
      );
1992
0
    } else if (field->label == PROTOBUF_C_LABEL_NONE) {
1993
0
      rv += unlabeled_field_pack_to_buffer(
1994
0
        field,
1995
0
        member,
1996
0
        buffer
1997
0
      );
1998
0
    } else {
1999
0
      rv += repeated_field_pack_to_buffer(
2000
0
        field,
2001
0
        *(const size_t *) qmember,
2002
0
        member,
2003
0
        buffer
2004
0
      );
2005
0
    }
2006
0
  }
2007
0
  for (i = 0; i < message->n_unknown_fields; i++)
2008
0
    rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
2009
2010
0
  return rv;
2011
0
}
2012
2013
/**
2014
 * \defgroup unpack unpacking implementation
2015
 *
2016
 * Routines mainly used by the unpacking functions.
2017
 *
2018
 * \ingroup internal
2019
 * @{
2020
 */
2021
2022
static inline int
2023
int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
2024
0
{
2025
0
  unsigned n;
2026
0
  unsigned start;
2027
2028
0
  if (n_ranges == 0)
2029
0
    return -1;
2030
0
  start = 0;
2031
0
  n = n_ranges;
2032
0
  while (n > 1) {
2033
0
    unsigned mid = start + n / 2;
2034
2035
0
    if (value < ranges[mid].start_value) {
2036
0
      n = mid - start;
2037
0
    } else if (value >= ranges[mid].start_value +
2038
0
         (int) (ranges[mid + 1].orig_index -
2039
0
          ranges[mid].orig_index))
2040
0
    {
2041
0
      unsigned new_start = mid + 1;
2042
0
      n = start + n - new_start;
2043
0
      start = new_start;
2044
0
    } else
2045
0
      return (value - ranges[mid].start_value) +
2046
0
          ranges[mid].orig_index;
2047
0
  }
2048
0
  if (n > 0) {
2049
0
    unsigned start_orig_index = ranges[start].orig_index;
2050
0
    unsigned range_size =
2051
0
      ranges[start + 1].orig_index - start_orig_index;
2052
2053
0
    if (ranges[start].start_value <= value &&
2054
0
        value < (int) (ranges[start].start_value + range_size))
2055
0
    {
2056
0
      return (value - ranges[start].start_value) +
2057
0
          start_orig_index;
2058
0
    }
2059
0
  }
2060
0
  return -1;
2061
0
}
2062
2063
static size_t
2064
parse_tag_and_wiretype(size_t len,
2065
           const uint8_t *data,
2066
           uint32_t *tag_out,
2067
           uint8_t *wiretype_out)
2068
0
{
2069
0
  unsigned max_rv = len > 5 ? 5 : len;
2070
0
  uint32_t tag = (data[0] & 0x7f) >> 3;
2071
0
  unsigned shift = 4;
2072
0
  unsigned rv;
2073
2074
  /* 0 is not a valid tag value */
2075
0
  if ((data[0] & 0xf8) == 0) {
2076
0
    return 0;
2077
0
  }
2078
2079
0
  *wiretype_out = data[0] & 7;
2080
0
  if ((data[0] & 0x80) == 0) {
2081
0
    *tag_out = tag;
2082
0
    return 1;
2083
0
  }
2084
0
  for (rv = 1; rv < max_rv; rv++) {
2085
0
    if (data[rv] & 0x80) {
2086
0
      tag |= (data[rv] & 0x7f) << shift;
2087
0
      shift += 7;
2088
0
    } else {
2089
0
      tag |= data[rv] << shift;
2090
0
      *tag_out = tag;
2091
0
      return rv + 1;
2092
0
    }
2093
0
  }
2094
0
  return 0; /* error: bad header */
2095
0
}
2096
2097
/* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
2098
0
#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
2099
typedef struct ScannedMember ScannedMember;
2100
/** Field as it's being read. */
2101
struct ScannedMember {
2102
  uint32_t tag;              /**< Field tag. */
2103
  uint8_t wire_type;         /**< Field type. */
2104
  uint8_t length_prefix_len; /**< Prefix length. */
2105
  const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
2106
  size_t len;                /**< Field length. */
2107
  const uint8_t *data;       /**< Pointer to field data. */
2108
};
2109
2110
static inline size_t
2111
scan_length_prefixed_data(size_t len, const uint8_t *data,
2112
        size_t *prefix_len_out)
2113
0
{
2114
0
  unsigned hdr_max = len < 5 ? len : 5;
2115
0
  unsigned hdr_len;
2116
0
  size_t val = 0;
2117
0
  unsigned i;
2118
0
  unsigned shift = 0;
2119
2120
0
  for (i = 0; i < hdr_max; i++) {
2121
0
    val |= ((size_t)data[i] & 0x7f) << shift;
2122
0
    shift += 7;
2123
0
    if ((data[i] & 0x80) == 0)
2124
0
      break;
2125
0
  }
2126
0
  if (i == hdr_max) {
2127
0
    PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
2128
0
    return 0;
2129
0
  }
2130
0
  hdr_len = i + 1;
2131
0
  *prefix_len_out = hdr_len;
2132
0
  if (val > INT_MAX) {
2133
    // Protobuf messages should always be less than 2 GiB in size.
2134
    // We also want to return early here so that hdr_len + val does
2135
    // not overflow on 32-bit systems.
2136
0
    PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large",
2137
0
      (unsigned long int)val);
2138
0
    return 0;
2139
0
  }
2140
0
  if (hdr_len + val > len) {
2141
0
    PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu",
2142
0
      (unsigned long int)val);
2143
0
    return 0;
2144
0
  }
2145
0
  return hdr_len + val;
2146
0
}
2147
2148
static size_t
2149
max_b128_numbers(size_t len, const uint8_t *data)
2150
0
{
2151
0
  size_t rv = 0;
2152
0
  while (len--)
2153
0
    if ((*data++ & 0x80) == 0)
2154
0
      ++rv;
2155
0
  return rv;
2156
0
}
2157
2158
/**@}*/
2159
2160
/**
2161
 * Merge earlier message into a latter message.
2162
 *
2163
 * For numeric types and strings, if the same value appears multiple
2164
 * times, the parser accepts the last value it sees. For embedded
2165
 * message fields, the parser merges multiple instances of the same
2166
 * field. That is, all singular scalar fields in the latter instance
2167
 * replace those in the former, singular embedded messages are merged,
2168
 * and repeated fields are concatenated.
2169
 *
2170
 * The earlier message should be freed after calling this function, as
2171
 * some of its fields may have been reused and changed to their default
2172
 * values during the merge.
2173
 */
2174
static protobuf_c_boolean
2175
merge_messages(ProtobufCMessage *earlier_msg,
2176
         ProtobufCMessage *latter_msg,
2177
         ProtobufCAllocator *allocator)
2178
0
{
2179
0
  unsigned i;
2180
0
  const ProtobufCFieldDescriptor *fields =
2181
0
    latter_msg->descriptor->fields;
2182
0
  for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
2183
0
    if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
2184
0
      size_t *n_earlier =
2185
0
        STRUCT_MEMBER_PTR(size_t, earlier_msg,
2186
0
              fields[i].quantifier_offset);
2187
0
      uint8_t **p_earlier =
2188
0
        STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
2189
0
              fields[i].offset);
2190
0
      size_t *n_latter =
2191
0
        STRUCT_MEMBER_PTR(size_t, latter_msg,
2192
0
              fields[i].quantifier_offset);
2193
0
      uint8_t **p_latter =
2194
0
        STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
2195
0
              fields[i].offset);
2196
2197
0
      if (*n_earlier > 0) {
2198
0
        if (*n_latter > 0) {
2199
          /* Concatenate the repeated field */
2200
0
          size_t el_size =
2201
0
            sizeof_elt_in_repeated_array(fields[i].type);
2202
0
          uint8_t *new_field;
2203
2204
0
          new_field = do_alloc(allocator,
2205
0
            (*n_earlier + *n_latter) * el_size);
2206
0
          if (!new_field)
2207
0
            return FALSE;
2208
2209
0
          memcpy(new_field, *p_earlier,
2210
0
                 *n_earlier * el_size);
2211
0
          memcpy(new_field +
2212
0
                 *n_earlier * el_size,
2213
0
                 *p_latter,
2214
0
                 *n_latter * el_size);
2215
2216
0
          do_free(allocator, *p_latter);
2217
0
          do_free(allocator, *p_earlier);
2218
0
          *p_latter = new_field;
2219
0
          *n_latter = *n_earlier + *n_latter;
2220
0
        } else {
2221
          /* Zero copy the repeated field from the earlier message */
2222
0
          *n_latter = *n_earlier;
2223
0
          *p_latter = *p_earlier;
2224
0
        }
2225
        /* Make sure the field does not get double freed */
2226
0
        *n_earlier = 0;
2227
0
        *p_earlier = 0;
2228
0
      }
2229
0
    } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL ||
2230
0
         fields[i].label == PROTOBUF_C_LABEL_NONE) {
2231
0
      const ProtobufCFieldDescriptor *field;
2232
0
      uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t,
2233
0
                     earlier_msg,
2234
0
                     fields[i].
2235
0
                     quantifier_offset);
2236
0
      uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t,
2237
0
                    latter_msg,
2238
0
                    fields[i].
2239
0
                    quantifier_offset);
2240
0
      protobuf_c_boolean need_to_merge = FALSE;
2241
0
      void *earlier_elem;
2242
0
      void *latter_elem;
2243
0
      const void *def_val;
2244
2245
0
      if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
2246
0
        if (*latter_case_p == 0) {
2247
          /* lookup correct oneof field */
2248
0
          int field_index =
2249
0
            int_range_lookup(
2250
0
              latter_msg->descriptor
2251
0
              ->n_field_ranges,
2252
0
              latter_msg->descriptor
2253
0
              ->field_ranges,
2254
0
              *earlier_case_p);
2255
0
          if (field_index < 0)
2256
0
            return FALSE;
2257
0
          field = latter_msg->descriptor->fields +
2258
0
            field_index;
2259
0
        } else {
2260
          /* Oneof is present in the latter message, move on */
2261
0
          continue;
2262
0
        }
2263
0
      } else {
2264
0
        field = &fields[i];
2265
0
      }
2266
2267
0
      earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset);
2268
0
      latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset);
2269
0
      def_val = field->default_value;
2270
2271
0
      switch (field->type) {
2272
0
      case PROTOBUF_C_TYPE_MESSAGE: {
2273
0
        ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem;
2274
0
        ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem;
2275
0
        if (em != NULL) {
2276
0
          if (lm != NULL) {
2277
0
            if (!merge_messages(em, lm, allocator))
2278
0
              return FALSE;
2279
            /* Already merged */
2280
0
            need_to_merge = FALSE;
2281
0
          } else {
2282
            /* Zero copy the message */
2283
0
            need_to_merge = TRUE;
2284
0
          }
2285
0
        }
2286
0
        break;
2287
0
      }
2288
0
      case PROTOBUF_C_TYPE_BYTES: {
2289
0
        uint8_t *e_data =
2290
0
          ((ProtobufCBinaryData *) earlier_elem)->data;
2291
0
        uint8_t *l_data =
2292
0
          ((ProtobufCBinaryData *) latter_elem)->data;
2293
0
        const ProtobufCBinaryData *d_bd =
2294
0
          (ProtobufCBinaryData *) def_val;
2295
2296
0
        need_to_merge =
2297
0
          (e_data != NULL &&
2298
0
           (d_bd == NULL ||
2299
0
            e_data != d_bd->data)) &&
2300
0
          (l_data == NULL ||
2301
0
           (d_bd != NULL &&
2302
0
            l_data == d_bd->data));
2303
0
        break;
2304
0
      }
2305
0
      case PROTOBUF_C_TYPE_STRING: {
2306
0
        char *e_str = *(char **) earlier_elem;
2307
0
        char *l_str = *(char **) latter_elem;
2308
0
        const char *d_str = def_val;
2309
2310
0
        need_to_merge = e_str != d_str && l_str == d_str;
2311
0
        break;
2312
0
      }
2313
0
      default: {
2314
        /* Could be has field or case enum, the logic is
2315
         * equivalent, since 0 (FALSE) means not set for
2316
         * oneof */
2317
0
        need_to_merge = (*earlier_case_p != 0) &&
2318
0
            (*latter_case_p == 0);
2319
0
        break;
2320
0
      }
2321
0
      }
2322
2323
0
      if (need_to_merge) {
2324
0
        size_t el_size =
2325
0
          sizeof_elt_in_repeated_array(field->type);
2326
0
        memcpy(latter_elem, earlier_elem, el_size);
2327
        /*
2328
         * Reset the element from the old message to 0
2329
         * to make sure earlier message deallocation
2330
         * doesn't corrupt zero-copied data in the new
2331
         * message, earlier message will be freed after
2332
         * this function is called anyway
2333
         */
2334
0
        memset(earlier_elem, 0, el_size);
2335
2336
0
        if (field->quantifier_offset != 0) {
2337
          /* Set the has field or the case enum,
2338
           * if applicable */
2339
0
          *latter_case_p = *earlier_case_p;
2340
0
          *earlier_case_p = 0;
2341
0
        }
2342
0
      }
2343
0
    }
2344
0
  }
2345
0
  return TRUE;
2346
0
}
2347
2348
/**
2349
 * Count packed elements.
2350
 *
2351
 * Given a raw slab of packed-repeated values, determine the number of
2352
 * elements. This function detects certain kinds of errors but not
2353
 * others; the remaining error checking is done by
2354
 * parse_packed_repeated_member().
2355
 */
2356
static protobuf_c_boolean
2357
count_packed_elements(ProtobufCType type,
2358
          size_t len, const uint8_t *data, size_t *count_out)
2359
0
{
2360
0
  switch (type) {
2361
0
  case PROTOBUF_C_TYPE_SFIXED32:
2362
0
  case PROTOBUF_C_TYPE_FIXED32:
2363
0
  case PROTOBUF_C_TYPE_FLOAT:
2364
0
    if (len % 4 != 0) {
2365
0
      PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
2366
0
      return FALSE;
2367
0
    }
2368
0
    *count_out = len / 4;
2369
0
    return TRUE;
2370
0
  case PROTOBUF_C_TYPE_SFIXED64:
2371
0
  case PROTOBUF_C_TYPE_FIXED64:
2372
0
  case PROTOBUF_C_TYPE_DOUBLE:
2373
0
    if (len % 8 != 0) {
2374
0
      PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
2375
0
      return FALSE;
2376
0
    }
2377
0
    *count_out = len / 8;
2378
0
    return TRUE;
2379
0
  case PROTOBUF_C_TYPE_ENUM:
2380
0
  case PROTOBUF_C_TYPE_INT32:
2381
0
  case PROTOBUF_C_TYPE_SINT32:
2382
0
  case PROTOBUF_C_TYPE_UINT32:
2383
0
  case PROTOBUF_C_TYPE_INT64:
2384
0
  case PROTOBUF_C_TYPE_SINT64:
2385
0
  case PROTOBUF_C_TYPE_UINT64:
2386
0
    *count_out = max_b128_numbers(len, data);
2387
0
    return TRUE;
2388
0
  case PROTOBUF_C_TYPE_BOOL:
2389
0
    *count_out = len;
2390
0
    return TRUE;
2391
0
  case PROTOBUF_C_TYPE_STRING:
2392
0
  case PROTOBUF_C_TYPE_BYTES:
2393
0
  case PROTOBUF_C_TYPE_MESSAGE:
2394
0
  default:
2395
0
    PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
2396
0
    return FALSE;
2397
0
  }
2398
0
}
2399
2400
static inline uint32_t
2401
parse_uint32(unsigned len, const uint8_t *data)
2402
0
{
2403
0
  uint32_t rv = data[0] & 0x7f;
2404
0
  if (len > 1) {
2405
0
    rv |= ((uint32_t) (data[1] & 0x7f) << 7);
2406
0
    if (len > 2) {
2407
0
      rv |= ((uint32_t) (data[2] & 0x7f) << 14);
2408
0
      if (len > 3) {
2409
0
        rv |= ((uint32_t) (data[3] & 0x7f) << 21);
2410
0
        if (len > 4)
2411
0
          rv |= ((uint32_t) (data[4]) << 28);
2412
0
      }
2413
0
    }
2414
0
  }
2415
0
  return rv;
2416
0
}
2417
2418
static inline uint32_t
2419
parse_int32(unsigned len, const uint8_t *data)
2420
0
{
2421
0
  return parse_uint32(len, data);
2422
0
}
2423
2424
static inline int32_t
2425
unzigzag32(uint32_t v)
2426
0
{
2427
  // Note:  Using unsigned types prevents undefined behavior
2428
0
  return (int32_t)((v >> 1) ^ (~(v & 1) + 1));
2429
0
}
2430
2431
static inline uint32_t
2432
parse_fixed_uint32(const uint8_t *data)
2433
0
{
2434
0
#if !defined(WORDS_BIGENDIAN)
2435
0
  uint32_t t;
2436
0
  memcpy(&t, data, 4);
2437
0
  return t;
2438
#else
2439
  return data[0] |
2440
    ((uint32_t) (data[1]) << 8) |
2441
    ((uint32_t) (data[2]) << 16) |
2442
    ((uint32_t) (data[3]) << 24);
2443
#endif
2444
0
}
2445
2446
static uint64_t
2447
parse_uint64(unsigned len, const uint8_t *data)
2448
0
{
2449
0
  unsigned shift, i;
2450
0
  uint64_t rv;
2451
2452
0
  if (len < 5)
2453
0
    return parse_uint32(len, data);
2454
0
  rv = ((uint64_t) (data[0] & 0x7f)) |
2455
0
    ((uint64_t) (data[1] & 0x7f) << 7) |
2456
0
    ((uint64_t) (data[2] & 0x7f) << 14) |
2457
0
    ((uint64_t) (data[3] & 0x7f) << 21);
2458
0
  shift = 28;
2459
0
  for (i = 4; i < len; i++) {
2460
0
    rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
2461
0
    shift += 7;
2462
0
  }
2463
0
  return rv;
2464
0
}
2465
2466
static inline int64_t
2467
unzigzag64(uint64_t v)
2468
0
{
2469
  // Note:  Using unsigned types prevents undefined behavior
2470
0
  return (int64_t)((v >> 1) ^ (~(v & 1) + 1));
2471
0
}
2472
2473
static inline uint64_t
2474
parse_fixed_uint64(const uint8_t *data)
2475
0
{
2476
0
#if !defined(WORDS_BIGENDIAN)
2477
0
  uint64_t t;
2478
0
  memcpy(&t, data, 8);
2479
0
  return t;
2480
#else
2481
  return (uint64_t) parse_fixed_uint32(data) |
2482
    (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
2483
#endif
2484
0
}
2485
2486
static protobuf_c_boolean
2487
parse_boolean(unsigned len, const uint8_t *data)
2488
0
{
2489
0
  unsigned i;
2490
0
  for (i = 0; i < len; i++)
2491
0
    if (data[i] & 0x7f)
2492
0
      return TRUE;
2493
0
  return FALSE;
2494
0
}
2495
2496
static protobuf_c_boolean
2497
parse_required_member(ScannedMember *scanned_member,
2498
          void *member,
2499
          ProtobufCAllocator *allocator,
2500
          protobuf_c_boolean maybe_clear)
2501
0
{
2502
0
  unsigned len = scanned_member->len;
2503
0
  const uint8_t *data = scanned_member->data;
2504
0
  uint8_t wire_type = scanned_member->wire_type;
2505
2506
0
  switch (scanned_member->field->type) {
2507
0
  case PROTOBUF_C_TYPE_ENUM:
2508
0
  case PROTOBUF_C_TYPE_INT32:
2509
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2510
0
      return FALSE;
2511
0
    *(int32_t *) member = parse_int32(len, data);
2512
0
    return TRUE;
2513
0
  case PROTOBUF_C_TYPE_UINT32:
2514
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2515
0
      return FALSE;
2516
0
    *(uint32_t *) member = parse_uint32(len, data);
2517
0
    return TRUE;
2518
0
  case PROTOBUF_C_TYPE_SINT32:
2519
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2520
0
      return FALSE;
2521
0
    *(int32_t *) member = unzigzag32(parse_uint32(len, data));
2522
0
    return TRUE;
2523
0
  case PROTOBUF_C_TYPE_SFIXED32:
2524
0
  case PROTOBUF_C_TYPE_FIXED32:
2525
0
  case PROTOBUF_C_TYPE_FLOAT:
2526
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
2527
0
      return FALSE;
2528
0
    *(uint32_t *) member = parse_fixed_uint32(data);
2529
0
    return TRUE;
2530
0
  case PROTOBUF_C_TYPE_INT64:
2531
0
  case PROTOBUF_C_TYPE_UINT64:
2532
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2533
0
      return FALSE;
2534
0
    *(uint64_t *) member = parse_uint64(len, data);
2535
0
    return TRUE;
2536
0
  case PROTOBUF_C_TYPE_SINT64:
2537
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
2538
0
      return FALSE;
2539
0
    *(int64_t *) member = unzigzag64(parse_uint64(len, data));
2540
0
    return TRUE;
2541
0
  case PROTOBUF_C_TYPE_SFIXED64:
2542
0
  case PROTOBUF_C_TYPE_FIXED64:
2543
0
  case PROTOBUF_C_TYPE_DOUBLE:
2544
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
2545
0
      return FALSE;
2546
0
    *(uint64_t *) member = parse_fixed_uint64(data);
2547
0
    return TRUE;
2548
0
  case PROTOBUF_C_TYPE_BOOL:
2549
0
    *(protobuf_c_boolean *) member = parse_boolean(len, data);
2550
0
    return TRUE;
2551
0
  case PROTOBUF_C_TYPE_STRING: {
2552
0
    char **pstr = member;
2553
0
    unsigned pref_len = scanned_member->length_prefix_len;
2554
2555
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2556
0
      return FALSE;
2557
2558
0
    if (maybe_clear && *pstr != NULL) {
2559
0
      const char *def = scanned_member->field->default_value;
2560
0
      if (*pstr != NULL && *pstr != def)
2561
0
        do_free(allocator, *pstr);
2562
0
    }
2563
0
    *pstr = do_alloc(allocator, len - pref_len + 1);
2564
0
    if (*pstr == NULL)
2565
0
      return FALSE;
2566
0
    memcpy(*pstr, data + pref_len, len - pref_len);
2567
0
    (*pstr)[len - pref_len] = 0;
2568
0
    return TRUE;
2569
0
  }
2570
0
  case PROTOBUF_C_TYPE_BYTES: {
2571
0
    ProtobufCBinaryData *bd = member;
2572
0
    const ProtobufCBinaryData *def_bd;
2573
0
    unsigned pref_len = scanned_member->length_prefix_len;
2574
2575
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2576
0
      return FALSE;
2577
2578
0
    def_bd = scanned_member->field->default_value;
2579
0
    if (maybe_clear &&
2580
0
        bd->data != NULL &&
2581
0
        (def_bd == NULL || bd->data != def_bd->data))
2582
0
    {
2583
0
      do_free(allocator, bd->data);
2584
0
    }
2585
0
    if (len > pref_len) {
2586
0
      bd->data = do_alloc(allocator, len - pref_len);
2587
0
      if (bd->data == NULL)
2588
0
        return FALSE;
2589
0
      memcpy(bd->data, data + pref_len, len - pref_len);
2590
0
    } else {
2591
0
      bd->data = NULL;
2592
0
    }
2593
0
    bd->len = len - pref_len;
2594
0
    return TRUE;
2595
0
  }
2596
0
  case PROTOBUF_C_TYPE_MESSAGE: {
2597
0
    ProtobufCMessage **pmessage = member;
2598
0
    ProtobufCMessage *subm;
2599
0
    const ProtobufCMessage *def_mess;
2600
0
    protobuf_c_boolean merge_successful = TRUE;
2601
0
    unsigned pref_len = scanned_member->length_prefix_len;
2602
2603
0
    if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
2604
0
      return FALSE;
2605
2606
0
    def_mess = scanned_member->field->default_value;
2607
0
    subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
2608
0
             allocator,
2609
0
             len - pref_len,
2610
0
             data + pref_len);
2611
2612
0
    if (maybe_clear &&
2613
0
        *pmessage != NULL &&
2614
0
        *pmessage != def_mess)
2615
0
    {
2616
0
      if (subm != NULL)
2617
0
        merge_successful = merge_messages(*pmessage, subm, allocator);
2618
      /* Delete the previous message */
2619
0
      protobuf_c_message_free_unpacked(*pmessage, allocator);
2620
0
    }
2621
0
    *pmessage = subm;
2622
0
    if (subm == NULL || !merge_successful)
2623
0
      return FALSE;
2624
0
    return TRUE;
2625
0
  }
2626
0
  }
2627
0
  return FALSE;
2628
0
}
2629
2630
static protobuf_c_boolean
2631
parse_oneof_member (ScannedMember *scanned_member,
2632
        void *member,
2633
        ProtobufCMessage *message,
2634
        ProtobufCAllocator *allocator)
2635
0
{
2636
0
  uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message,
2637
0
                 scanned_member->field->quantifier_offset);
2638
2639
  /* If we have already parsed a member of this oneof, free it. */
2640
0
  if (*oneof_case != 0) {
2641
0
    const ProtobufCFieldDescriptor *old_field;
2642
0
    size_t el_size;
2643
    /* lookup field */
2644
0
    int field_index =
2645
0
      int_range_lookup(message->descriptor->n_field_ranges,
2646
0
           message->descriptor->field_ranges,
2647
0
           *oneof_case);
2648
0
    if (field_index < 0)
2649
0
      return FALSE;
2650
0
    old_field = message->descriptor->fields + field_index;
2651
0
    el_size = sizeof_elt_in_repeated_array(old_field->type);
2652
2653
0
    switch (old_field->type) {
2654
0
          case PROTOBUF_C_TYPE_STRING: {
2655
0
      char **pstr = member;
2656
0
      const char *def = old_field->default_value;
2657
0
      if (*pstr != NULL && *pstr != def)
2658
0
        do_free(allocator, *pstr);
2659
0
      break;
2660
0
          }
2661
0
    case PROTOBUF_C_TYPE_BYTES: {
2662
0
      ProtobufCBinaryData *bd = member;
2663
0
      const ProtobufCBinaryData *def_bd = old_field->default_value;
2664
0
      if (bd->data != NULL &&
2665
0
         (def_bd == NULL || bd->data != def_bd->data))
2666
0
      {
2667
0
        do_free(allocator, bd->data);
2668
0
      }
2669
0
      break;
2670
0
          }
2671
0
    case PROTOBUF_C_TYPE_MESSAGE: {
2672
0
      ProtobufCMessage **pmessage = member;
2673
0
      const ProtobufCMessage *def_mess = old_field->default_value;
2674
0
      if (*pmessage != NULL && *pmessage != def_mess)
2675
0
        protobuf_c_message_free_unpacked(*pmessage, allocator);
2676
0
      break;
2677
0
          }
2678
0
    default:
2679
0
      break;
2680
0
    }
2681
2682
0
    memset (member, 0, el_size);
2683
0
  }
2684
0
  if (!parse_required_member (scanned_member, member, allocator, TRUE))
2685
0
    return FALSE;
2686
2687
0
  *oneof_case = scanned_member->tag;
2688
0
  return TRUE;
2689
0
}
2690
2691
2692
static protobuf_c_boolean
2693
parse_optional_member(ScannedMember *scanned_member,
2694
          void *member,
2695
          ProtobufCMessage *message,
2696
          ProtobufCAllocator *allocator)
2697
0
{
2698
0
  if (!parse_required_member(scanned_member, member, allocator, TRUE))
2699
0
    return FALSE;
2700
0
  if (scanned_member->field->quantifier_offset != 0)
2701
0
    STRUCT_MEMBER(protobuf_c_boolean,
2702
0
            message,
2703
0
            scanned_member->field->quantifier_offset) = TRUE;
2704
0
  return TRUE;
2705
0
}
2706
2707
static protobuf_c_boolean
2708
parse_repeated_member(ScannedMember *scanned_member,
2709
          void *member,
2710
          ProtobufCMessage *message,
2711
          ProtobufCAllocator *allocator)
2712
0
{
2713
0
  const ProtobufCFieldDescriptor *field = scanned_member->field;
2714
0
  size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2715
0
  size_t siz = sizeof_elt_in_repeated_array(field->type);
2716
0
  char *array = *(char **) member;
2717
2718
0
  if (!parse_required_member(scanned_member, array + siz * (*p_n),
2719
0
           allocator, FALSE))
2720
0
  {
2721
0
    return FALSE;
2722
0
  }
2723
0
  *p_n += 1;
2724
0
  return TRUE;
2725
0
}
2726
2727
static unsigned
2728
scan_varint(unsigned len, const uint8_t *data)
2729
0
{
2730
0
  unsigned i;
2731
0
  if (len > 10)
2732
0
    len = 10;
2733
0
  for (i = 0; i < len; i++)
2734
0
    if ((data[i] & 0x80) == 0)
2735
0
      break;
2736
0
  if (i == len)
2737
0
    return 0;
2738
0
  return i + 1;
2739
0
}
2740
2741
static protobuf_c_boolean
2742
parse_packed_repeated_member(ScannedMember *scanned_member,
2743
           void *member,
2744
           ProtobufCMessage *message)
2745
0
{
2746
0
  const ProtobufCFieldDescriptor *field = scanned_member->field;
2747
0
  size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
2748
0
  size_t siz = sizeof_elt_in_repeated_array(field->type);
2749
0
  void *array = *(char **) member + siz * (*p_n);
2750
0
  const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
2751
0
  size_t rem = scanned_member->len - scanned_member->length_prefix_len;
2752
0
  size_t count = 0;
2753
#if defined(WORDS_BIGENDIAN)
2754
  unsigned i;
2755
#endif
2756
2757
0
  switch (field->type) {
2758
0
  case PROTOBUF_C_TYPE_SFIXED32:
2759
0
  case PROTOBUF_C_TYPE_FIXED32:
2760
0
  case PROTOBUF_C_TYPE_FLOAT:
2761
0
    count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
2762
0
#if !defined(WORDS_BIGENDIAN)
2763
0
    goto no_unpacking_needed;
2764
#else
2765
    for (i = 0; i < count; i++) {
2766
      ((uint32_t *) array)[i] = parse_fixed_uint32(at);
2767
      at += 4;
2768
    }
2769
    break;
2770
#endif
2771
0
  case PROTOBUF_C_TYPE_SFIXED64:
2772
0
  case PROTOBUF_C_TYPE_FIXED64:
2773
0
  case PROTOBUF_C_TYPE_DOUBLE:
2774
0
    count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
2775
0
#if !defined(WORDS_BIGENDIAN)
2776
0
    goto no_unpacking_needed;
2777
#else
2778
    for (i = 0; i < count; i++) {
2779
      ((uint64_t *) array)[i] = parse_fixed_uint64(at);
2780
      at += 8;
2781
    }
2782
    break;
2783
#endif
2784
0
  case PROTOBUF_C_TYPE_ENUM:
2785
0
  case PROTOBUF_C_TYPE_INT32:
2786
0
    while (rem > 0) {
2787
0
      unsigned s = scan_varint(rem, at);
2788
0
      if (s == 0) {
2789
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
2790
0
        return FALSE;
2791
0
      }
2792
0
      ((int32_t *) array)[count++] = parse_int32(s, at);
2793
0
      at += s;
2794
0
      rem -= s;
2795
0
    }
2796
0
    break;
2797
0
  case PROTOBUF_C_TYPE_SINT32:
2798
0
    while (rem > 0) {
2799
0
      unsigned s = scan_varint(rem, at);
2800
0
      if (s == 0) {
2801
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
2802
0
        return FALSE;
2803
0
      }
2804
0
      ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
2805
0
      at += s;
2806
0
      rem -= s;
2807
0
    }
2808
0
    break;
2809
0
  case PROTOBUF_C_TYPE_UINT32:
2810
0
    while (rem > 0) {
2811
0
      unsigned s = scan_varint(rem, at);
2812
0
      if (s == 0) {
2813
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
2814
0
        return FALSE;
2815
0
      }
2816
0
      ((uint32_t *) array)[count++] = parse_uint32(s, at);
2817
0
      at += s;
2818
0
      rem -= s;
2819
0
    }
2820
0
    break;
2821
2822
0
  case PROTOBUF_C_TYPE_SINT64:
2823
0
    while (rem > 0) {
2824
0
      unsigned s = scan_varint(rem, at);
2825
0
      if (s == 0) {
2826
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
2827
0
        return FALSE;
2828
0
      }
2829
0
      ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
2830
0
      at += s;
2831
0
      rem -= s;
2832
0
    }
2833
0
    break;
2834
0
  case PROTOBUF_C_TYPE_INT64:
2835
0
  case PROTOBUF_C_TYPE_UINT64:
2836
0
    while (rem > 0) {
2837
0
      unsigned s = scan_varint(rem, at);
2838
0
      if (s == 0) {
2839
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
2840
0
        return FALSE;
2841
0
      }
2842
0
      ((int64_t *) array)[count++] = parse_uint64(s, at);
2843
0
      at += s;
2844
0
      rem -= s;
2845
0
    }
2846
0
    break;
2847
0
  case PROTOBUF_C_TYPE_BOOL:
2848
0
    while (rem > 0) {
2849
0
      unsigned s = scan_varint(rem, at);
2850
0
      if (s == 0) {
2851
0
        PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
2852
0
        return FALSE;
2853
0
      }
2854
0
      ((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at);
2855
0
      at += s;
2856
0
      rem -= s;
2857
0
    }
2858
0
    break;
2859
0
  default:
2860
0
    PROTOBUF_C__ASSERT_NOT_REACHED();
2861
0
  }
2862
0
  *p_n += count;
2863
0
  return TRUE;
2864
2865
0
#if !defined(WORDS_BIGENDIAN)
2866
0
no_unpacking_needed:
2867
0
  memcpy(array, at, count * siz);
2868
0
  *p_n += count;
2869
0
  return TRUE;
2870
0
#endif
2871
0
}
2872
2873
static protobuf_c_boolean
2874
is_packable_type(ProtobufCType type)
2875
0
{
2876
0
  return
2877
0
    type != PROTOBUF_C_TYPE_STRING &&
2878
0
    type != PROTOBUF_C_TYPE_BYTES &&
2879
0
    type != PROTOBUF_C_TYPE_MESSAGE;
2880
0
}
2881
2882
static protobuf_c_boolean
2883
parse_member(ScannedMember *scanned_member,
2884
       ProtobufCMessage *message,
2885
       ProtobufCAllocator *allocator)
2886
0
{
2887
0
  const ProtobufCFieldDescriptor *field = scanned_member->field;
2888
0
  void *member;
2889
2890
0
  if (field == NULL) {
2891
0
    ProtobufCMessageUnknownField *ufield =
2892
0
      message->unknown_fields +
2893
0
      (message->n_unknown_fields++);
2894
0
    ufield->tag = scanned_member->tag;
2895
0
    ufield->wire_type = scanned_member->wire_type;
2896
0
    ufield->len = scanned_member->len;
2897
0
    ufield->data = do_alloc(allocator, scanned_member->len);
2898
0
    if (ufield->data == NULL)
2899
0
      return FALSE;
2900
0
    memcpy(ufield->data, scanned_member->data, ufield->len);
2901
0
    return TRUE;
2902
0
  }
2903
0
  member = (char *) message + field->offset;
2904
0
  switch (field->label) {
2905
0
  case PROTOBUF_C_LABEL_REQUIRED:
2906
0
    return parse_required_member(scanned_member, member,
2907
0
               allocator, TRUE);
2908
0
  case PROTOBUF_C_LABEL_OPTIONAL:
2909
0
  case PROTOBUF_C_LABEL_NONE:
2910
0
    if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
2911
0
      return parse_oneof_member(scanned_member, member,
2912
0
              message, allocator);
2913
0
    } else {
2914
0
      return parse_optional_member(scanned_member, member,
2915
0
                 message, allocator);
2916
0
    }
2917
0
  case PROTOBUF_C_LABEL_REPEATED:
2918
0
    if (scanned_member->wire_type ==
2919
0
        PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
2920
0
        (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
2921
0
         is_packable_type(field->type)))
2922
0
    {
2923
0
      return parse_packed_repeated_member(scanned_member,
2924
0
                  member, message);
2925
0
    } else {
2926
0
      return parse_repeated_member(scanned_member,
2927
0
                 member, message,
2928
0
                 allocator);
2929
0
    }
2930
0
  }
2931
0
  PROTOBUF_C__ASSERT_NOT_REACHED();
2932
0
  return 0;
2933
0
}
2934
2935
/**
2936
 * Initialise messages generated by old code.
2937
 *
2938
 * This function is used if desc->message_init == NULL (which occurs
2939
 * for old code, and which would be useful to support allocating
2940
 * descriptors dynamically).
2941
 */
2942
static void
2943
message_init_generic(const ProtobufCMessageDescriptor *desc,
2944
         ProtobufCMessage *message)
2945
0
{
2946
0
  unsigned i;
2947
2948
0
  memset(message, 0, desc->sizeof_message);
2949
0
  message->descriptor = desc;
2950
0
  for (i = 0; i < desc->n_fields; i++) {
2951
0
    if (desc->fields[i].default_value != NULL &&
2952
0
        desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
2953
0
    {
2954
0
      void *field =
2955
0
        STRUCT_MEMBER_P(message, desc->fields[i].offset);
2956
0
      const void *dv = desc->fields[i].default_value;
2957
2958
0
      switch (desc->fields[i].type) {
2959
0
      case PROTOBUF_C_TYPE_INT32:
2960
0
      case PROTOBUF_C_TYPE_SINT32:
2961
0
      case PROTOBUF_C_TYPE_SFIXED32:
2962
0
      case PROTOBUF_C_TYPE_UINT32:
2963
0
      case PROTOBUF_C_TYPE_FIXED32:
2964
0
      case PROTOBUF_C_TYPE_FLOAT:
2965
0
      case PROTOBUF_C_TYPE_ENUM:
2966
0
        memcpy(field, dv, 4);
2967
0
        break;
2968
0
      case PROTOBUF_C_TYPE_INT64:
2969
0
      case PROTOBUF_C_TYPE_SINT64:
2970
0
      case PROTOBUF_C_TYPE_SFIXED64:
2971
0
      case PROTOBUF_C_TYPE_UINT64:
2972
0
      case PROTOBUF_C_TYPE_FIXED64:
2973
0
      case PROTOBUF_C_TYPE_DOUBLE:
2974
0
        memcpy(field, dv, 8);
2975
0
        break;
2976
0
      case PROTOBUF_C_TYPE_BOOL:
2977
0
        memcpy(field, dv, sizeof(protobuf_c_boolean));
2978
0
        break;
2979
0
      case PROTOBUF_C_TYPE_BYTES:
2980
0
        memcpy(field, dv, sizeof(ProtobufCBinaryData));
2981
0
        break;
2982
2983
0
      case PROTOBUF_C_TYPE_STRING:
2984
0
      case PROTOBUF_C_TYPE_MESSAGE:
2985
        /*
2986
         * The next line essentially implements a cast
2987
         * from const, which is totally unavoidable.
2988
         */
2989
0
        *(const void **) field = dv;
2990
0
        break;
2991
0
      }
2992
0
    }
2993
0
  }
2994
0
}
2995
2996
/**@}*/
2997
2998
/*
2999
 * ScannedMember slabs (an unpacking implementation detail). Before doing real
3000
 * unpacking, we first scan through the elements to see how many there are (for
3001
 * repeated fields), and which field to use (for non-repeated fields given
3002
 * twice).
3003
 *
3004
 * In order to avoid allocations for small messages, we keep a stack-allocated
3005
 * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
3006
 * fill that up, we allocate each slab twice as large as the previous one.
3007
 */
3008
0
#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
3009
3010
/*
3011
 * The number of slabs, including the stack-allocated ones; choose the number so
3012
 * that we would overflow if we needed a slab larger than provided.
3013
 */
3014
#define MAX_SCANNED_MEMBER_SLAB     \
3015
0
  (sizeof(unsigned int)*8 - 1     \
3016
0
   - BOUND_SIZEOF_SCANNED_MEMBER_LOG2    \
3017
0
   - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
3018
3019
#define REQUIRED_FIELD_BITMAP_SET(index)  \
3020
0
  (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8)))
3021
3022
#define REQUIRED_FIELD_BITMAP_IS_SET(index) \
3023
0
  (required_fields_bitmap[(index)/8] & (1UL<<((index)%8)))
3024
3025
ProtobufCMessage *
3026
protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
3027
        ProtobufCAllocator *allocator,
3028
        size_t len, const uint8_t *data)
3029
0
{
3030
0
  ProtobufCMessage *rv;
3031
0
  size_t rem = len;
3032
0
  const uint8_t *at = data;
3033
0
  const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
3034
0
  ScannedMember first_member_slab[1UL <<
3035
0
          FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
3036
3037
  /*
3038
   * scanned_member_slabs[i] is an array of arrays of ScannedMember.
3039
   * The first slab (scanned_member_slabs[0] is just a pointer to
3040
   * first_member_slab), above. All subsequent slabs will be allocated
3041
   * using the allocator.
3042
   */
3043
0
  ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
3044
0
  unsigned which_slab = 0; /* the slab we are currently populating */
3045
0
  unsigned in_slab_index = 0; /* number of members in the slab */
3046
0
  size_t n_unknown = 0;
3047
0
  unsigned f;
3048
0
  unsigned j;
3049
0
  unsigned i_slab;
3050
0
  unsigned last_field_index = 0;
3051
0
  unsigned required_fields_bitmap_len;
3052
0
  unsigned char required_fields_bitmap_stack[16];
3053
0
  unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
3054
0
  protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
3055
3056
0
  ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
3057
3058
0
  if (allocator == NULL)
3059
0
    allocator = &protobuf_c__allocator;
3060
3061
0
  rv = do_alloc(allocator, desc->sizeof_message);
3062
0
  if (!rv)
3063
0
    return (NULL);
3064
0
  scanned_member_slabs[0] = first_member_slab;
3065
3066
0
  required_fields_bitmap_len = (desc->n_fields + 7) / 8;
3067
0
  if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
3068
0
    required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
3069
0
    if (!required_fields_bitmap) {
3070
0
      do_free(allocator, rv);
3071
0
      return (NULL);
3072
0
    }
3073
0
    required_fields_bitmap_alloced = TRUE;
3074
0
  }
3075
0
  memset(required_fields_bitmap, 0, required_fields_bitmap_len);
3076
3077
  /*
3078
   * Generated code always defines "message_init". However, we provide a
3079
   * fallback for (1) users of old protobuf-c generated-code that do not
3080
   * provide the function, and (2) descriptors constructed from some other
3081
   * source (most likely, direct construction from the .proto file).
3082
   */
3083
0
  if (desc->message_init != NULL)
3084
0
    protobuf_c_message_init(desc, rv);
3085
0
  else
3086
0
    message_init_generic(desc, rv);
3087
3088
0
  while (rem > 0) {
3089
0
    uint32_t tag;
3090
0
    uint8_t wire_type;
3091
0
    size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
3092
0
    const ProtobufCFieldDescriptor *field;
3093
0
    ScannedMember tmp;
3094
3095
0
    if (used == 0) {
3096
0
      PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
3097
0
            (unsigned) (at - data));
3098
0
      goto error_cleanup_during_scan;
3099
0
    }
3100
    /*
3101
     * \todo Consider optimizing for field[1].id == tag, if field[1]
3102
     * exists!
3103
     */
3104
0
    if (last_field == NULL || last_field->id != tag) {
3105
      /* lookup field */
3106
0
      int field_index =
3107
0
          int_range_lookup(desc->n_field_ranges,
3108
0
               desc->field_ranges,
3109
0
               tag);
3110
0
      if (field_index < 0) {
3111
0
        field = NULL;
3112
0
        n_unknown++;
3113
0
      } else {
3114
0
        field = desc->fields + field_index;
3115
0
        last_field = field;
3116
0
        last_field_index = field_index;
3117
0
      }
3118
0
    } else {
3119
0
      field = last_field;
3120
0
    }
3121
3122
0
    if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
3123
0
      REQUIRED_FIELD_BITMAP_SET(last_field_index);
3124
3125
0
    at += used;
3126
0
    rem -= used;
3127
0
    tmp.tag = tag;
3128
0
    tmp.wire_type = wire_type;
3129
0
    tmp.field = field;
3130
0
    tmp.data = at;
3131
0
    tmp.length_prefix_len = 0;
3132
3133
0
    switch (wire_type) {
3134
0
    case PROTOBUF_C_WIRE_TYPE_VARINT: {
3135
0
      unsigned max_len = rem < 10 ? rem : 10;
3136
0
      unsigned i;
3137
3138
0
      for (i = 0; i < max_len; i++)
3139
0
        if ((at[i] & 0x80) == 0)
3140
0
          break;
3141
0
      if (i == max_len) {
3142
0
        PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
3143
0
              (unsigned) (at - data));
3144
0
        goto error_cleanup_during_scan;
3145
0
      }
3146
0
      tmp.len = i + 1;
3147
0
      break;
3148
0
    }
3149
0
    case PROTOBUF_C_WIRE_TYPE_64BIT:
3150
0
      if (rem < 8) {
3151
0
        PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
3152
0
              (unsigned) (at - data));
3153
0
        goto error_cleanup_during_scan;
3154
0
      }
3155
0
      tmp.len = 8;
3156
0
      break;
3157
0
    case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
3158
0
      size_t pref_len;
3159
3160
0
      tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
3161
0
      if (tmp.len == 0) {
3162
        /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
3163
0
        goto error_cleanup_during_scan;
3164
0
      }
3165
0
      tmp.length_prefix_len = pref_len;
3166
0
      break;
3167
0
    }
3168
0
    case PROTOBUF_C_WIRE_TYPE_32BIT:
3169
0
      if (rem < 4) {
3170
0
        PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
3171
0
                (unsigned) (at - data));
3172
0
        goto error_cleanup_during_scan;
3173
0
      }
3174
0
      tmp.len = 4;
3175
0
      break;
3176
0
    default:
3177
0
      PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
3178
0
            wire_type, (unsigned) (at - data));
3179
0
      goto error_cleanup_during_scan;
3180
0
    }
3181
3182
0
    if (in_slab_index == (1UL <<
3183
0
      (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
3184
0
    {
3185
0
      size_t size;
3186
3187
0
      in_slab_index = 0;
3188
0
      if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
3189
0
        PROTOBUF_C_UNPACK_ERROR("too many fields");
3190
0
        goto error_cleanup_during_scan;
3191
0
      }
3192
0
      which_slab++;
3193
0
      size = sizeof(ScannedMember)
3194
0
        << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
3195
0
      scanned_member_slabs[which_slab] = do_alloc(allocator, size);
3196
0
      if (scanned_member_slabs[which_slab] == NULL)
3197
0
        goto error_cleanup_during_scan;
3198
0
    }
3199
0
    scanned_member_slabs[which_slab][in_slab_index++] = tmp;
3200
3201
0
    if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
3202
0
      size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
3203
0
                  field->quantifier_offset);
3204
0
      if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
3205
0
          (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
3206
0
           is_packable_type(field->type)))
3207
0
      {
3208
0
        size_t count;
3209
0
        if (!count_packed_elements(field->type,
3210
0
                 tmp.len -
3211
0
                 tmp.length_prefix_len,
3212
0
                 tmp.data +
3213
0
                 tmp.length_prefix_len,
3214
0
                 &count))
3215
0
        {
3216
0
          PROTOBUF_C_UNPACK_ERROR("counting packed elements");
3217
0
          goto error_cleanup_during_scan;
3218
0
        }
3219
0
        *n += count;
3220
0
      } else {
3221
0
        *n += 1;
3222
0
      }
3223
0
    }
3224
3225
0
    at += tmp.len;
3226
0
    rem -= tmp.len;
3227
0
  }
3228
3229
  /* allocate space for repeated fields, also check that all required fields have been set */
3230
0
  for (f = 0; f < desc->n_fields; f++) {
3231
0
    const ProtobufCFieldDescriptor *field = desc->fields + f;
3232
0
    if (field->label == PROTOBUF_C_LABEL_REPEATED) {
3233
0
      size_t siz =
3234
0
          sizeof_elt_in_repeated_array(field->type);
3235
0
      size_t *n_ptr =
3236
0
          STRUCT_MEMBER_PTR(size_t, rv,
3237
0
                field->quantifier_offset);
3238
0
      if (*n_ptr != 0) {
3239
0
        unsigned n = *n_ptr;
3240
0
        void *a;
3241
0
        *n_ptr = 0;
3242
0
        assert(rv->descriptor != NULL);
3243
0
#define CLEAR_REMAINING_N_PTRS()                                              \
3244
0
              for(f++;f < desc->n_fields; f++)                                \
3245
0
                {                                                             \
3246
0
                  field = desc->fields + f;                                   \
3247
0
                  if (field->label == PROTOBUF_C_LABEL_REPEATED)              \
3248
0
                    STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
3249
0
                }
3250
0
        a = do_alloc(allocator, siz * n);
3251
0
        if (!a) {
3252
0
          CLEAR_REMAINING_N_PTRS();
3253
0
          goto error_cleanup;
3254
0
        }
3255
0
        STRUCT_MEMBER(void *, rv, field->offset) = a;
3256
0
      }
3257
0
    } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
3258
0
      if (field->default_value == NULL &&
3259
0
          !REQUIRED_FIELD_BITMAP_IS_SET(f))
3260
0
      {
3261
0
        CLEAR_REMAINING_N_PTRS();
3262
0
        PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
3263
0
              desc->name, field->name);
3264
0
        goto error_cleanup;
3265
0
      }
3266
0
    }
3267
0
  }
3268
0
#undef CLEAR_REMAINING_N_PTRS
3269
3270
  /* allocate space for unknown fields */
3271
0
  if (n_unknown) {
3272
0
    rv->unknown_fields = do_alloc(allocator,
3273
0
                n_unknown * sizeof(ProtobufCMessageUnknownField));
3274
0
    if (rv->unknown_fields == NULL)
3275
0
      goto error_cleanup;
3276
0
  }
3277
3278
  /* do real parsing */
3279
0
  for (i_slab = 0; i_slab <= which_slab; i_slab++) {
3280
0
    unsigned max = (i_slab == which_slab) ?
3281
0
      in_slab_index : (1UL << (i_slab + 4));
3282
0
    ScannedMember *slab = scanned_member_slabs[i_slab];
3283
3284
0
    for (j = 0; j < max; j++) {
3285
0
      if (!parse_member(slab + j, rv, allocator)) {
3286
0
        PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
3287
0
              slab->field ? slab->field->name : "*unknown-field*",
3288
0
          desc->name);
3289
0
        goto error_cleanup;
3290
0
      }
3291
0
    }
3292
0
  }
3293
3294
  /* cleanup */
3295
0
  for (j = 1; j <= which_slab; j++)
3296
0
    do_free(allocator, scanned_member_slabs[j]);
3297
0
  if (required_fields_bitmap_alloced)
3298
0
    do_free(allocator, required_fields_bitmap);
3299
0
  return rv;
3300
3301
0
error_cleanup:
3302
0
  protobuf_c_message_free_unpacked(rv, allocator);
3303
0
  for (j = 1; j <= which_slab; j++)
3304
0
    do_free(allocator, scanned_member_slabs[j]);
3305
0
  if (required_fields_bitmap_alloced)
3306
0
    do_free(allocator, required_fields_bitmap);
3307
0
  return NULL;
3308
3309
0
error_cleanup_during_scan:
3310
0
  do_free(allocator, rv);
3311
0
  for (j = 1; j <= which_slab; j++)
3312
0
    do_free(allocator, scanned_member_slabs[j]);
3313
0
  if (required_fields_bitmap_alloced)
3314
0
    do_free(allocator, required_fields_bitmap);
3315
0
  return NULL;
3316
0
}
3317
3318
void
3319
protobuf_c_message_free_unpacked(ProtobufCMessage *message,
3320
         ProtobufCAllocator *allocator)
3321
0
{
3322
0
  const ProtobufCMessageDescriptor *desc;
3323
0
  unsigned f;
3324
3325
0
  if (message == NULL)
3326
0
    return;
3327
3328
0
  desc = message->descriptor;
3329
3330
0
  ASSERT_IS_MESSAGE(message);
3331
3332
0
  if (allocator == NULL)
3333
0
    allocator = &protobuf_c__allocator;
3334
0
  message->descriptor = NULL;
3335
0
  for (f = 0; f < desc->n_fields; f++) {
3336
0
    if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) &&
3337
0
        desc->fields[f].id !=
3338
0
        STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset))
3339
0
    {
3340
      /* This is not the selected oneof, skip it */
3341
0
      continue;
3342
0
    }
3343
3344
0
    if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
3345
0
      size_t n = STRUCT_MEMBER(size_t,
3346
0
             message,
3347
0
             desc->fields[f].quantifier_offset);
3348
0
      void *arr = STRUCT_MEMBER(void *,
3349
0
              message,
3350
0
              desc->fields[f].offset);
3351
3352
0
      if (arr != NULL) {
3353
0
        if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3354
0
          unsigned i;
3355
0
          for (i = 0; i < n; i++)
3356
0
            do_free(allocator, ((char **) arr)[i]);
3357
0
        } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3358
0
          unsigned i;
3359
0
          for (i = 0; i < n; i++)
3360
0
            do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
3361
0
        } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3362
0
          unsigned i;
3363
0
          for (i = 0; i < n; i++)
3364
0
            protobuf_c_message_free_unpacked(
3365
0
              ((ProtobufCMessage **) arr)[i],
3366
0
              allocator
3367
0
            );
3368
0
        }
3369
0
        do_free(allocator, arr);
3370
0
      }
3371
0
    } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
3372
0
      char *str = STRUCT_MEMBER(char *, message,
3373
0
              desc->fields[f].offset);
3374
3375
0
      if (str && str != desc->fields[f].default_value)
3376
0
        do_free(allocator, str);
3377
0
    } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
3378
0
      void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
3379
0
               desc->fields[f].offset).data;
3380
0
      const ProtobufCBinaryData *default_bd;
3381
3382
0
      default_bd = desc->fields[f].default_value;
3383
0
      if (data != NULL &&
3384
0
          (default_bd == NULL ||
3385
0
           default_bd->data != data))
3386
0
      {
3387
0
        do_free(allocator, data);
3388
0
      }
3389
0
    } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
3390
0
      ProtobufCMessage *sm;
3391
3392
0
      sm = STRUCT_MEMBER(ProtobufCMessage *, message,
3393
0
             desc->fields[f].offset);
3394
0
      if (sm && sm != desc->fields[f].default_value)
3395
0
        protobuf_c_message_free_unpacked(sm, allocator);
3396
0
    }
3397
0
  }
3398
3399
0
  for (f = 0; f < message->n_unknown_fields; f++)
3400
0
    do_free(allocator, message->unknown_fields[f].data);
3401
0
  if (message->unknown_fields != NULL)
3402
0
    do_free(allocator, message->unknown_fields);
3403
3404
0
  do_free(allocator, message);
3405
0
}
3406
3407
void
3408
protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
3409
      void *message)
3410
0
{
3411
0
  descriptor->message_init((ProtobufCMessage *) (message));
3412
0
}
3413
3414
protobuf_c_boolean
3415
protobuf_c_message_check(const ProtobufCMessage *message)
3416
0
{
3417
0
  unsigned i;
3418
3419
0
  if (!message ||
3420
0
      !message->descriptor ||
3421
0
      message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
3422
0
  {
3423
0
    return FALSE;
3424
0
  }
3425
3426
0
  for (i = 0; i < message->descriptor->n_fields; i++) {
3427
0
    const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
3428
0
    ProtobufCType type = f->type;
3429
0
    ProtobufCLabel label = f->label;
3430
0
    void *field = STRUCT_MEMBER_P (message, f->offset);
3431
3432
0
    if (f->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
3433
0
      const uint32_t *oneof_case = STRUCT_MEMBER_P (message, f->quantifier_offset);
3434
0
      if (f->id != *oneof_case) {
3435
0
        continue; //Do not check if it is an unpopulated oneof member.
3436
0
      }
3437
0
    }
3438
3439
0
    if (label == PROTOBUF_C_LABEL_REPEATED) {
3440
0
      size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
3441
3442
0
      if (*quantity > 0 && *(void **) field == NULL) {
3443
0
        return FALSE;
3444
0
      }
3445
3446
0
      if (type == PROTOBUF_C_TYPE_MESSAGE) {
3447
0
        ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
3448
0
        unsigned j;
3449
0
        for (j = 0; j < *quantity; j++) {
3450
0
          if (!protobuf_c_message_check(submessage[j]))
3451
0
            return FALSE;
3452
0
        }
3453
0
      } else if (type == PROTOBUF_C_TYPE_STRING) {
3454
0
        char **string = *(char ***) field;
3455
0
        unsigned j;
3456
0
        for (j = 0; j < *quantity; j++) {
3457
0
          if (!string[j])
3458
0
            return FALSE;
3459
0
        }
3460
0
      } else if (type == PROTOBUF_C_TYPE_BYTES) {
3461
0
        ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
3462
0
        unsigned j;
3463
0
        for (j = 0; j < *quantity; j++) {
3464
0
          if (bd[j].len > 0 && bd[j].data == NULL)
3465
0
            return FALSE;
3466
0
        }
3467
0
      }
3468
3469
0
    } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
3470
3471
0
      if (type == PROTOBUF_C_TYPE_MESSAGE) {
3472
0
        ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
3473
0
        if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
3474
0
          if (!protobuf_c_message_check(submessage))
3475
0
            return FALSE;
3476
0
        }
3477
0
      } else if (type == PROTOBUF_C_TYPE_STRING) {
3478
0
        char *string = *(char **) field;
3479
0
        if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
3480
0
          return FALSE;
3481
0
      } else if (type == PROTOBUF_C_TYPE_BYTES) {
3482
0
        protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
3483
0
        ProtobufCBinaryData *bd = field;
3484
0
        if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
3485
0
          if (bd->len > 0 && bd->data == NULL)
3486
0
            return FALSE;
3487
0
        }
3488
0
      }
3489
0
    }
3490
0
  }
3491
3492
0
  return TRUE;
3493
0
}
3494
3495
/* === services === */
3496
3497
typedef void (*GenericHandler) (void *service,
3498
        const ProtobufCMessage *input,
3499
        ProtobufCClosure closure,
3500
        void *closure_data);
3501
void
3502
protobuf_c_service_invoke_internal(ProtobufCService *service,
3503
           unsigned method_index,
3504
           const ProtobufCMessage *input,
3505
           ProtobufCClosure closure,
3506
           void *closure_data)
3507
0
{
3508
0
  GenericHandler *handlers;
3509
0
  GenericHandler handler;
3510
3511
  /*
3512
   * Verify that method_index is within range. If this fails, you are
3513
   * likely invoking a newly added method on an old service. (Although
3514
   * other memory corruption bugs can cause this assertion too.)
3515
   */
3516
0
  assert(method_index < service->descriptor->n_methods);
3517
3518
  /*
3519
   * Get the array of virtual methods (which are enumerated by the
3520
   * generated code).
3521
   */
3522
0
  handlers = (GenericHandler *) (service + 1);
3523
3524
  /*
3525
   * Get our method and invoke it.
3526
   * \todo Seems like handler == NULL is a situation that needs handling.
3527
   */
3528
0
  handler = handlers[method_index];
3529
0
  (*handler)(service, input, closure, closure_data);
3530
0
}
3531
3532
void
3533
protobuf_c_service_generated_init(ProtobufCService *service,
3534
          const ProtobufCServiceDescriptor *descriptor,
3535
          ProtobufCServiceDestroy destroy)
3536
0
{
3537
0
  ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
3538
0
  service->descriptor = descriptor;
3539
0
  service->destroy = destroy;
3540
0
  service->invoke = protobuf_c_service_invoke_internal;
3541
0
  memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
3542
0
}
3543
3544
void protobuf_c_service_destroy(ProtobufCService *service)
3545
0
{
3546
0
  service->destroy(service);
3547
0
}
3548
3549
/* --- querying the descriptors --- */
3550
3551
const ProtobufCEnumValue *
3552
protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
3553
               const char *name)
3554
0
{
3555
0
  unsigned start = 0;
3556
0
  unsigned count;
3557
3558
0
  if (desc == NULL || desc->values_by_name == NULL)
3559
0
    return NULL;
3560
3561
0
  count = desc->n_value_names;
3562
3563
0
  while (count > 1) {
3564
0
    unsigned mid = start + count / 2;
3565
0
    int rv = strcmp(desc->values_by_name[mid].name, name);
3566
0
    if (rv == 0)
3567
0
      return desc->values + desc->values_by_name[mid].index;
3568
0
    else if (rv < 0) {
3569
0
      count = start + count - (mid + 1);
3570
0
      start = mid + 1;
3571
0
    } else
3572
0
      count = mid - start;
3573
0
  }
3574
0
  if (count == 0)
3575
0
    return NULL;
3576
0
  if (strcmp(desc->values_by_name[start].name, name) == 0)
3577
0
    return desc->values + desc->values_by_name[start].index;
3578
0
  return NULL;
3579
0
}
3580
3581
const ProtobufCEnumValue *
3582
protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
3583
             int value)
3584
0
{
3585
0
  int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
3586
0
  if (rv < 0)
3587
0
    return NULL;
3588
0
  return desc->values + rv;
3589
0
}
3590
3591
const ProtobufCFieldDescriptor *
3592
protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
3593
            const char *name)
3594
0
{
3595
0
  unsigned start = 0;
3596
0
  unsigned count;
3597
0
  const ProtobufCFieldDescriptor *field;
3598
3599
0
  if (desc == NULL || desc->fields_sorted_by_name == NULL)
3600
0
    return NULL;
3601
3602
0
  count = desc->n_fields;
3603
3604
0
  while (count > 1) {
3605
0
    unsigned mid = start + count / 2;
3606
0
    int rv;
3607
0
    field = desc->fields + desc->fields_sorted_by_name[mid];
3608
0
    rv = strcmp(field->name, name);
3609
0
    if (rv == 0)
3610
0
      return field;
3611
0
    else if (rv < 0) {
3612
0
      count = start + count - (mid + 1);
3613
0
      start = mid + 1;
3614
0
    } else
3615
0
      count = mid - start;
3616
0
  }
3617
0
  if (count == 0)
3618
0
    return NULL;
3619
0
  field = desc->fields + desc->fields_sorted_by_name[start];
3620
0
  if (strcmp(field->name, name) == 0)
3621
0
    return field;
3622
0
  return NULL;
3623
0
}
3624
3625
const ProtobufCFieldDescriptor *
3626
protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
3627
          unsigned value)
3628
0
{
3629
0
  int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
3630
0
  if (rv < 0)
3631
0
    return NULL;
3632
0
  return desc->fields + rv;
3633
0
}
3634
3635
const ProtobufCMethodDescriptor *
3636
protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
3637
             const char *name)
3638
0
{
3639
0
  unsigned start = 0;
3640
0
  unsigned count;
3641
3642
0
  if (desc == NULL || desc->method_indices_by_name == NULL)
3643
0
    return NULL;
3644
3645
0
  count = desc->n_methods;
3646
3647
0
  while (count > 1) {
3648
0
    unsigned mid = start + count / 2;
3649
0
    unsigned mid_index = desc->method_indices_by_name[mid];
3650
0
    const char *mid_name = desc->methods[mid_index].name;
3651
0
    int rv = strcmp(mid_name, name);
3652
3653
0
    if (rv == 0)
3654
0
      return desc->methods + desc->method_indices_by_name[mid];
3655
0
    if (rv < 0) {
3656
0
      count = start + count - (mid + 1);
3657
0
      start = mid + 1;
3658
0
    } else {
3659
0
      count = mid - start;
3660
0
    }
3661
0
  }
3662
0
  if (count == 0)
3663
0
    return NULL;
3664
0
  if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
3665
0
    return desc->methods + desc->method_indices_by_name[start];
3666
0
  return NULL;
3667
0
}