Coverage Report

Created: 2023-03-10 07:33

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