Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/* pb_encode.c -- encode a protobuf using minimal resources
2
 *
3
 * 2011 Petteri Aimonen <jpa@kapsi.fi>
4
 */
5
 
6
#include "pb.h"
7
#include "pb_encode.h"
8
#include "pb_common.h"
9
 
10
/* Use the GCC warn_unused_result attribute to check that all return values
11
 * are propagated correctly. On other compilers and gcc before 3.4.0 just
12
 * ignore the annotation.
13
 */
14
#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
15
    #define checkreturn
16
#else
17
    #define checkreturn __attribute__((warn_unused_result))
18
#endif
19
 
20
/**************************************
21
 * Declarations internal to this file *
22
 **************************************/
23
typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn;
24
 
25
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
26
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func);
27
static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
28
static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
29
static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
30
static void *pb_const_cast(const void *p);
31
static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_t *field, const void *src);
32
static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
33
static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
34
static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
35
static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src);
36
static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src);
37
static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
38
static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src);
39
static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
40
static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src);
41
 
42
#ifdef PB_WITHOUT_64BIT
43
#define pb_int64_t int32_t
44
#define pb_uint64_t uint32_t
45
 
46
static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value);
47
#else
48
#define pb_int64_t int64_t
49
#define pb_uint64_t uint64_t
50
#endif
51
 
52
/* --- Function pointers to field encoders ---
53
 * Order in the array must match pb_action_t LTYPE numbering.
54
 */
55
static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
56
    &pb_enc_bool,
57
    &pb_enc_varint,
58
    &pb_enc_uvarint,
59
    &pb_enc_svarint,
60
    &pb_enc_fixed32,
61
    &pb_enc_fixed64,
62
 
63
    &pb_enc_bytes,
64
    &pb_enc_string,
65
    &pb_enc_submessage,
66
    NULL, /* extensions */
67
    &pb_enc_fixed_length_bytes
68
};
69
 
70
/*******************************
71
 * pb_ostream_t implementation *
72
 *******************************/
73
 
74
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
75
{
76
    size_t i;
77
    pb_byte_t *dest = (pb_byte_t*)stream->state;
78
    stream->state = dest + count;
79
 
80
    for (i = 0; i < count; i++)
81
        dest[i] = buf[i];
82
 
83
    return true;
84
}
85
 
86
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
87
{
88
    pb_ostream_t stream;
89
#ifdef PB_BUFFER_ONLY
90
    stream.callback = (void*)1; /* Just a marker value */
91
#else
92
    stream.callback = &buf_write;
93
#endif
94
    stream.state = buf;
95
    stream.max_size = bufsize;
96
    stream.bytes_written = 0;
97
#ifndef PB_NO_ERRMSG
98
    stream.errmsg = NULL;
99
#endif
100
    return stream;
101
}
102
 
103
bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
104
{
105
    if (count > 0 && stream->callback != NULL)
106
    {
107
        if (stream->bytes_written + count < stream->bytes_written ||
108
            stream->bytes_written + count > stream->max_size)
109
        {
110
            PB_RETURN_ERROR(stream, "stream full");
111
        }
112
 
113
#ifdef PB_BUFFER_ONLY
114
        if (!buf_write(stream, buf, count))
115
            PB_RETURN_ERROR(stream, "io error");
116
#else
117
        if (!stream->callback(stream, buf, count))
118
            PB_RETURN_ERROR(stream, "io error");
119
#endif
120
    }
121
 
122
    stream->bytes_written += count;
123
    return true;
124
}
125
 
126
/*************************
127
 * Encode a single field *
128
 *************************/
129
 
130
/* Read a bool value without causing undefined behavior even if the value
131
 * is invalid. See issue #434 and
132
 * https://stackoverflow.com/questions/27661768/weird-results-for-conditional
133
 */
134
static bool safe_read_bool(const void *pSize)
135
{
136
    const char *p = (const char *)pSize;
137
    size_t i;
138
    for (i = 0; i < sizeof(bool); i++)
139
    {
140
        if (p[i] != 0)
141
            return true;
142
    }
143
    return false;
144
}
145
 
146
/* Encode a static array. Handles the size calculations and possible packing. */
147
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
148
                         const void *pData, size_t count, pb_encoder_t func)
149
{
150
    size_t i;
151
    const void *p;
152
#ifndef PB_ENCODE_ARRAYS_UNPACKED
153
    size_t size;
154
#endif
155
 
156
    if (count == 0)
157
        return true;
158
 
159
    if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
160
        PB_RETURN_ERROR(stream, "array max size exceeded");
161
 
162
#ifndef PB_ENCODE_ARRAYS_UNPACKED
163
    /* We always pack arrays if the datatype allows it. */
164
    if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
165
    {
166
        if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
167
            return false;
168
 
169
        /* Determine the total size of packed array. */
170
        if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
171
        {
172
            size = 4 * count;
173
        }
174
        else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
175
        {
176
            size = 8 * count;
177
        }
178
        else
179
        {
180
            pb_ostream_t sizestream = PB_OSTREAM_SIZING;
181
            p = pData;
182
            for (i = 0; i < count; i++)
183
            {
184
                if (!func(&sizestream, field, p))
185
                    return false;
186
                p = (const char*)p + field->data_size;
187
            }
188
            size = sizestream.bytes_written;
189
        }
190
 
191
        if (!pb_encode_varint(stream, (pb_uint64_t)size))
192
            return false;
193
 
194
        if (stream->callback == NULL)
195
            return pb_write(stream, NULL, size); /* Just sizing.. */
196
 
197
        /* Write the data */
198
        p = pData;
199
        for (i = 0; i < count; i++)
200
        {
201
            if (!func(stream, field, p))
202
                return false;
203
            p = (const char*)p + field->data_size;
204
        }
205
    }
206
    else
207
#endif
208
    {
209
        p = pData;
210
        for (i = 0; i < count; i++)
211
        {
212
            if (!pb_encode_tag_for_field(stream, field))
213
                return false;
214
 
215
            /* Normally the data is stored directly in the array entries, but
216
             * for pointer-type string and bytes fields, the array entries are
217
             * actually pointers themselves also. So we have to dereference once
218
             * more to get to the actual data. */
219
            if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
220
                (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
221
                 PB_LTYPE(field->type) == PB_LTYPE_BYTES))
222
            {
223
                if (!func(stream, field, *(const void* const*)p))
224
                    return false;
225
            }
226
            else
227
            {
228
                if (!func(stream, field, p))
229
                    return false;
230
            }
231
            p = (const char*)p + field->data_size;
232
        }
233
    }
234
 
235
    return true;
236
}
237
 
238
/* In proto3, all fields are optional and are only encoded if their value is "non-zero".
239
 * This function implements the check for the zero value. */
240
static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData)
241
{
242
    pb_type_t type = field->type;
243
    const void *pSize = (const char*)pData + field->size_offset;
244
 
245
    if (PB_HTYPE(type) == PB_HTYPE_REQUIRED)
246
    {
247
        /* Required proto2 fields inside proto3 submessage, pretty rare case */
248
        return false;
249
    }
250
    else if (PB_HTYPE(type) == PB_HTYPE_REPEATED)
251
    {
252
        /* Repeated fields inside proto3 submessage: present if count != 0 */
253
        if (field->size_offset != 0)
254
            return *(const pb_size_t*)pSize == 0;
255
        else if (PB_ATYPE(type) == PB_ATYPE_STATIC)
256
            return false; /* Fixed length array */
257
    }
258
    else if (PB_HTYPE(type) == PB_HTYPE_ONEOF)
259
    {
260
        /* Oneof fields */
261
        return *(const pb_size_t*)pSize == 0;
262
    }
263
    else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset != 0)
264
    {
265
        /* Proto2 optional fields inside proto3 submessage */
266
        return safe_read_bool(pSize) == false;
267
    }
268
 
269
    /* Rest is proto3 singular fields */
270
 
271
    if (PB_ATYPE(type) == PB_ATYPE_STATIC)
272
    {
273
        if (PB_LTYPE(type) == PB_LTYPE_BYTES)
274
        {
275
            const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData;
276
            return bytes->size == 0;
277
        }
278
        else if (PB_LTYPE(type) == PB_LTYPE_STRING)
279
        {
280
            return *(const char*)pData == '\0';
281
        }
282
        else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES)
283
        {
284
            /* Fixed length bytes is only empty if its length is fixed
285
             * as 0. Which would be pretty strange, but we can check
286
             * it anyway. */
287
            return field->data_size == 0;
288
        }
289
        else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE)
290
        {
291
            /* Check all fields in the submessage to find if any of them
292
             * are non-zero. The comparison cannot be done byte-per-byte
293
             * because the C struct may contain padding bytes that must
294
             * be skipped.
295
             */
296
            pb_field_iter_t iter;
297
            if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData)))
298
            {
299
                do
300
                {
301
                    if (!pb_check_proto3_default_value(iter.pos, iter.pData))
302
                    {
303
                        return false;
304
                    }
305
                } while (pb_field_iter_next(&iter));
306
            }
307
            return true;
308
        }
309
    }
310
 
311
    /* Compares pointers to NULL in case of FT_POINTER */
312
    if (PB_ATYPE(type) == PB_ATYPE_POINTER && PB_LTYPE(type) > PB_LTYPE_LAST_PACKABLE)
313
    {
314
        return !*(const void**)((uintptr_t)pData);
315
    }
316
 
317
	{
318
	    /* Catch-all branch that does byte-per-byte comparison for zero value.
319
	     *
320
	     * This is for all pointer fields, and for static PB_LTYPE_VARINT,
321
	     * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also
322
	     * callback fields. These all have integer or pointer value which
323
	     * can be compared with 0.
324
	     */
325
	    pb_size_t i;
326
	    const char *p = (const char*)pData;
327
	    for (i = 0; i < field->data_size; i++)
328
	    {
329
	        if (p[i] != 0)
330
	        {
331
	            return false;
332
	        }
333
	    }
334
 
335
	    return true;
336
	}
337
}
338
 
339
/* Encode a field with static or pointer allocation, i.e. one whose data
340
 * is available to the encoder directly. */
341
static bool checkreturn encode_basic_field(pb_ostream_t *stream,
342
    const pb_field_t *field, const void *pData)
343
{
344
    pb_encoder_t func;
345
    bool implicit_has;
346
    const void *pSize = &implicit_has;
347
 
348
    func = PB_ENCODERS[PB_LTYPE(field->type)];
349
 
350
    if (field->size_offset)
351
    {
352
        /* Static optional, repeated or oneof field */
353
        pSize = (const char*)pData + field->size_offset;
354
    }
355
    else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL)
356
    {
357
        /* Proto3 style field, optional but without explicit has_ field. */
358
        implicit_has = !pb_check_proto3_default_value(field, pData);
359
    }
360
    else
361
    {
362
        /* Required field, always present */
363
        implicit_has = true;
364
    }
365
 
366
    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
367
    {
368
        /* pData is a pointer to the field, which contains pointer to
369
         * the data. If the 2nd pointer is NULL, it is interpreted as if
370
         * the has_field was false.
371
         */
372
        pData = *(const void* const*)pData;
373
        implicit_has = (pData != NULL);
374
    }
375
 
376
    switch (PB_HTYPE(field->type))
377
    {
378
        case PB_HTYPE_REQUIRED:
379
            if (!pData)
380
                PB_RETURN_ERROR(stream, "missing required field");
381
            if (!pb_encode_tag_for_field(stream, field))
382
                return false;
383
            if (!func(stream, field, pData))
384
                return false;
385
            break;
386
 
387
        case PB_HTYPE_OPTIONAL:
388
            if (safe_read_bool(pSize))
389
            {
390
                if (!pb_encode_tag_for_field(stream, field))
391
                    return false;
392
 
393
                if (!func(stream, field, pData))
394
                    return false;
395
            }
396
            break;
397
 
398
        case PB_HTYPE_REPEATED: {
399
            pb_size_t count;
400
            if (field->size_offset != 0) {
401
                count = *(const pb_size_t*)pSize;
402
            } else {
403
                count = field->array_size;
404
            }
405
            if (!encode_array(stream, field, pData, count, func))
406
                return false;
407
            break;
408
        }
409
 
410
        case PB_HTYPE_ONEOF:
411
            if (*(const pb_size_t*)pSize == field->tag)
412
            {
413
                if (!pb_encode_tag_for_field(stream, field))
414
                    return false;
415
 
416
                if (!func(stream, field, pData))
417
                    return false;
418
            }
419
            break;
420
 
421
        default:
422
            PB_RETURN_ERROR(stream, "invalid field type");
423
    }
424
 
425
    return true;
426
}
427
 
428
/* Encode a field with callback semantics. This means that a user function is
429
 * called to provide and encode the actual data. */
430
static bool checkreturn encode_callback_field(pb_ostream_t *stream,
431
    const pb_field_t *field, const void *pData)
432
{
433
    const pb_callback_t *callback = (const pb_callback_t*)pData;
434
 
435
#ifdef PB_OLD_CALLBACK_STYLE
436
    const void *arg = callback->arg;
437
#else
438
    void * const *arg = &(callback->arg);
439
#endif
440
 
441
    if (callback->funcs.encode != NULL)
442
    {
443
        if (!callback->funcs.encode(stream, field, arg))
444
            PB_RETURN_ERROR(stream, "callback error");
445
    }
446
    return true;
447
}
448
 
449
/* Encode a single field of any callback or static type. */
450
static bool checkreturn encode_field(pb_ostream_t *stream,
451
    const pb_field_t *field, const void *pData)
452
{
453
    switch (PB_ATYPE(field->type))
454
    {
455
        case PB_ATYPE_STATIC:
456
        case PB_ATYPE_POINTER:
457
            return encode_basic_field(stream, field, pData);
458
 
459
        case PB_ATYPE_CALLBACK:
460
            return encode_callback_field(stream, field, pData);
461
 
462
        default:
463
            PB_RETURN_ERROR(stream, "invalid field type");
464
    }
465
}
466
 
467
/* Default handler for extension fields. Expects to have a pb_field_t
468
 * pointer in the extension->type->arg field. */
469
static bool checkreturn default_extension_encoder(pb_ostream_t *stream,
470
    const pb_extension_t *extension)
471
{
472
    const pb_field_t *field = (const pb_field_t*)extension->type->arg;
473
 
474
    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
475
    {
476
        /* For pointer extensions, the pointer is stored directly
477
         * in the extension structure. This avoids having an extra
478
         * indirection. */
479
        return encode_field(stream, field, &extension->dest);
480
    }
481
    else
482
    {
483
        return encode_field(stream, field, extension->dest);
484
    }
485
}
486
 
487
/* Walk through all the registered extensions and give them a chance
488
 * to encode themselves. */
489
static bool checkreturn encode_extension_field(pb_ostream_t *stream,
490
    const pb_field_t *field, const void *pData)
491
{
492
    const pb_extension_t *extension = *(const pb_extension_t* const *)pData;
493
    PB_UNUSED(field);
494
 
495
    while (extension)
496
    {
497
        bool status;
498
        if (extension->type->encode)
499
            status = extension->type->encode(stream, extension);
500
        else
501
            status = default_extension_encoder(stream, extension);
502
 
503
        if (!status)
504
            return false;
505
 
506
        extension = extension->next;
507
    }
508
 
509
    return true;
510
}
511
 
512
/*********************
513
 * Encode all fields *
514
 *********************/
515
 
516
static void *pb_const_cast(const void *p)
517
{
518
    /* Note: this casts away const, in order to use the common field iterator
519
     * logic for both encoding and decoding. */
520
    union {
521
        void *p1;
522
        const void *p2;
523
    } t;
524
    t.p2 = p;
525
    return t.p1;
526
}
527
 
528
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
529
{
530
    pb_field_iter_t iter;
531
    if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct)))
532
        return true; /* Empty message type */
533
 
534
    do {
535
        if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION)
536
        {
537
            /* Special case for the extension field placeholder */
538
            if (!encode_extension_field(stream, iter.pos, iter.pData))
539
                return false;
540
        }
541
        else
542
        {
543
            /* Regular field */
544
            if (!encode_field(stream, iter.pos, iter.pData))
545
                return false;
546
        }
547
    } while (pb_field_iter_next(&iter));
548
 
549
    return true;
550
}
551
 
552
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
553
{
554
    return pb_encode_submessage(stream, fields, src_struct);
555
}
556
 
557
bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
558
{
559
    const pb_byte_t zero = 0;
560
 
561
    if (!pb_encode(stream, fields, src_struct))
562
        return false;
563
 
564
    return pb_write(stream, &zero, 1);
565
}
566
 
567
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
568
{
569
    pb_ostream_t stream = PB_OSTREAM_SIZING;
570
 
571
    if (!pb_encode(&stream, fields, src_struct))
572
        return false;
573
 
574
    *size = stream.bytes_written;
575
    return true;
576
}
577
 
578
/********************
579
 * Helper functions *
580
 ********************/
581
 
582
#ifdef PB_WITHOUT_64BIT
583
bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value)
584
{
585
  pb_byte_t buffer[10];
586
  size_t i = 0;
587
  size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */
588
 
589
  while (value)
590
  {
591
    buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
592
    value >>= 7;
593
    if (compensation)
594
    {
595
      /* re-set all the compensation bits we can or need */
596
      size_t bits = compensation > 7 ? 7 : compensation;
597
      value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */
598
      compensation -= bits;
599
    }
600
    i++;
601
  }
602
  buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */
603
 
604
  return pb_write(stream, buffer, i);
605
}
606
#endif
607
 
608
bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value)
609
{
610
    pb_byte_t buffer[10];
611
    size_t i = 0;
612
 
613
    if (value <= 0x7F)
614
    {
615
        pb_byte_t v = (pb_byte_t)value;
616
        return pb_write(stream, &v, 1);
617
    }
618
 
619
    while (value)
620
    {
621
        buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80);
622
        value >>= 7;
623
        i++;
624
    }
625
    buffer[i-1] &= 0x7F; /* Unset top bit on last byte */
626
 
627
    return pb_write(stream, buffer, i);
628
}
629
 
630
bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value)
631
{
632
    pb_uint64_t zigzagged;
633
    if (value < 0)
634
        zigzagged = ~((pb_uint64_t)value << 1);
635
    else
636
        zigzagged = (pb_uint64_t)value << 1;
637
 
638
    return pb_encode_varint(stream, zigzagged);
639
}
640
 
641
bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value)
642
{
643
    uint32_t val = *(const uint32_t*)value;
644
    pb_byte_t bytes[4];
645
    bytes[0] = (pb_byte_t)(val & 0xFF);
646
    bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
647
    bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
648
    bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
649
    return pb_write(stream, bytes, 4);
650
}
651
 
652
#ifndef PB_WITHOUT_64BIT
653
bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value)
654
{
655
    uint64_t val = *(const uint64_t*)value;
656
    pb_byte_t bytes[8];
657
    bytes[0] = (pb_byte_t)(val & 0xFF);
658
    bytes[1] = (pb_byte_t)((val >> 8) & 0xFF);
659
    bytes[2] = (pb_byte_t)((val >> 16) & 0xFF);
660
    bytes[3] = (pb_byte_t)((val >> 24) & 0xFF);
661
    bytes[4] = (pb_byte_t)((val >> 32) & 0xFF);
662
    bytes[5] = (pb_byte_t)((val >> 40) & 0xFF);
663
    bytes[6] = (pb_byte_t)((val >> 48) & 0xFF);
664
    bytes[7] = (pb_byte_t)((val >> 56) & 0xFF);
665
    return pb_write(stream, bytes, 8);
666
}
667
#endif
668
 
669
bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
670
{
671
    pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype;
672
    return pb_encode_varint(stream, tag);
673
}
674
 
675
bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
676
{
677
    pb_wire_type_t wiretype;
678
    switch (PB_LTYPE(field->type))
679
    {
680
        case PB_LTYPE_BOOL:
681
        case PB_LTYPE_VARINT:
682
        case PB_LTYPE_UVARINT:
683
        case PB_LTYPE_SVARINT:
684
            wiretype = PB_WT_VARINT;
685
            break;
686
 
687
        case PB_LTYPE_FIXED32:
688
            wiretype = PB_WT_32BIT;
689
            break;
690
 
691
        case PB_LTYPE_FIXED64:
692
            wiretype = PB_WT_64BIT;
693
            break;
694
 
695
        case PB_LTYPE_BYTES:
696
        case PB_LTYPE_STRING:
697
        case PB_LTYPE_SUBMESSAGE:
698
        case PB_LTYPE_FIXED_LENGTH_BYTES:
699
            wiretype = PB_WT_STRING;
700
            break;
701
 
702
        default:
703
            PB_RETURN_ERROR(stream, "invalid field type");
704
    }
705
 
706
    return pb_encode_tag(stream, wiretype, field->tag);
707
}
708
 
709
bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
710
{
711
    if (!pb_encode_varint(stream, (pb_uint64_t)size))
712
        return false;
713
 
714
    return pb_write(stream, buffer, size);
715
}
716
 
717
bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
718
{
719
    /* First calculate the message size using a non-writing substream. */
720
    pb_ostream_t substream = PB_OSTREAM_SIZING;
721
    size_t size;
722
    bool status;
723
 
724
    if (!pb_encode(&substream, fields, src_struct))
725
    {
726
#ifndef PB_NO_ERRMSG
727
        stream->errmsg = substream.errmsg;
728
#endif
729
        return false;
730
    }
731
 
732
    size = substream.bytes_written;
733
 
734
    if (!pb_encode_varint(stream, (pb_uint64_t)size))
735
        return false;
736
 
737
    if (stream->callback == NULL)
738
        return pb_write(stream, NULL, size); /* Just sizing */
739
 
740
    if (stream->bytes_written + size > stream->max_size)
741
        PB_RETURN_ERROR(stream, "stream full");
742
 
743
    /* Use a substream to verify that a callback doesn't write more than
744
     * what it did the first time. */
745
    substream.callback = stream->callback;
746
    substream.state = stream->state;
747
    substream.max_size = size;
748
    substream.bytes_written = 0;
749
#ifndef PB_NO_ERRMSG
750
    substream.errmsg = NULL;
751
#endif
752
 
753
    status = pb_encode(&substream, fields, src_struct);
754
 
755
    stream->bytes_written += substream.bytes_written;
756
    stream->state = substream.state;
757
#ifndef PB_NO_ERRMSG
758
    stream->errmsg = substream.errmsg;
759
#endif
760
 
761
    if (substream.bytes_written != size)
762
        PB_RETURN_ERROR(stream, "submsg size changed");
763
 
764
    return status;
765
}
766
 
767
/* Field encoders */
768
 
769
static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_t *field, const void *src)
770
{
771
    uint32_t value = safe_read_bool(src) ? 1 : 0;
772
    PB_UNUSED(field);
773
    return pb_encode_varint(stream, value);
774
}
775
 
776
static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
777
{
778
    pb_int64_t value = 0;
779
 
780
    if (field->data_size == sizeof(int_least8_t))
781
        value = *(const int_least8_t*)src;
782
    else if (field->data_size == sizeof(int_least16_t))
783
        value = *(const int_least16_t*)src;
784
    else if (field->data_size == sizeof(int32_t))
785
        value = *(const int32_t*)src;
786
    else if (field->data_size == sizeof(pb_int64_t))
787
        value = *(const pb_int64_t*)src;
788
    else
789
        PB_RETURN_ERROR(stream, "invalid data_size");
790
 
791
#ifdef PB_WITHOUT_64BIT
792
    if (value < 0)
793
      return pb_encode_negative_varint(stream, (pb_uint64_t)value);
794
    else
795
#endif
796
      return pb_encode_varint(stream, (pb_uint64_t)value);
797
}
798
 
799
static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
800
{
801
    pb_uint64_t value = 0;
802
 
803
    if (field->data_size == sizeof(uint_least8_t))
804
        value = *(const uint_least8_t*)src;
805
    else if (field->data_size == sizeof(uint_least16_t))
806
        value = *(const uint_least16_t*)src;
807
    else if (field->data_size == sizeof(uint32_t))
808
        value = *(const uint32_t*)src;
809
    else if (field->data_size == sizeof(pb_uint64_t))
810
        value = *(const pb_uint64_t*)src;
811
    else
812
        PB_RETURN_ERROR(stream, "invalid data_size");
813
 
814
    return pb_encode_varint(stream, value);
815
}
816
 
817
static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
818
{
819
    pb_int64_t value = 0;
820
 
821
    if (field->data_size == sizeof(int_least8_t))
822
        value = *(const int_least8_t*)src;
823
    else if (field->data_size == sizeof(int_least16_t))
824
        value = *(const int_least16_t*)src;
825
    else if (field->data_size == sizeof(int32_t))
826
        value = *(const int32_t*)src;
827
    else if (field->data_size == sizeof(pb_int64_t))
828
        value = *(const pb_int64_t*)src;
829
    else
830
        PB_RETURN_ERROR(stream, "invalid data_size");
831
 
832
    return pb_encode_svarint(stream, value);
833
}
834
 
835
static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src)
836
{
837
    PB_UNUSED(field);
838
#ifndef PB_WITHOUT_64BIT
839
    return pb_encode_fixed64(stream, src);
840
#else
841
    PB_UNUSED(src);
842
    PB_RETURN_ERROR(stream, "no 64bit support");
843
#endif
844
}
845
 
846
static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src)
847
{
848
    PB_UNUSED(field);
849
    return pb_encode_fixed32(stream, src);
850
}
851
 
852
static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
853
{
854
    const pb_bytes_array_t *bytes = NULL;
855
    size_t allocsize;
856
 
857
    bytes = (const pb_bytes_array_t*)src;
858
 
859
    if (src == NULL)
860
    {
861
        /* Treat null pointer as an empty bytes field */
862
        return pb_encode_string(stream, NULL, 0);
863
    }
864
 
865
    allocsize = PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size);
866
    if (allocsize < bytes->size ||
867
        (PB_ATYPE(field->type) == PB_ATYPE_STATIC && allocsize > field->data_size))
868
    {
869
        PB_RETURN_ERROR(stream, "bytes size exceeded");
870
    }
871
 
872
    return pb_encode_string(stream, bytes->bytes, bytes->size);
873
}
874
 
875
static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
876
{
877
    size_t size = 0;
878
    size_t max_size = field->data_size;
879
    const char *p = (const char*)src;
880
 
881
    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
882
        max_size = (size_t)-1;
883
 
884
    if (src == NULL)
885
    {
886
        size = 0; /* Treat null pointer as an empty string */
887
    }
888
    else
889
    {
890
        /* strnlen() is not always available, so just use a loop */
891
        while (size < max_size && *p != '\0')
892
        {
893
            size++;
894
            p++;
895
        }
896
    }
897
 
898
    return pb_encode_string(stream, (const pb_byte_t*)src, size);
899
}
900
 
901
static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
902
{
903
    if (field->ptr == NULL)
904
        PB_RETURN_ERROR(stream, "invalid field descriptor");
905
 
906
    return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
907
}
908
 
909
static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
910
{
911
    return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size);
912
}
913