1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
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//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "GPBCodedOutputStream_PackagePrivate.h"
32
33#import <mach/vm_param.h>
34
35#import "GPBArray.h"
36#import "GPBUnknownFieldSet_PackagePrivate.h"
37#import "GPBUtilities_PackagePrivate.h"
38
39// Structure for containing state of a GPBCodedInputStream. Brought out into
40// a struct so that we can inline several common functions instead of dealing
41// with overhead of ObjC dispatch.
42typedef struct GPBOutputBufferState {
43  uint8_t *bytes;
44  size_t size;
45  size_t position;
46  NSOutputStream *output;
47} GPBOutputBufferState;
48
49@implementation GPBCodedOutputStream {
50  GPBOutputBufferState state_;
51  NSMutableData *buffer_;
52}
53
54static const int32_t LITTLE_ENDIAN_32_SIZE = sizeof(uint32_t);
55static const int32_t LITTLE_ENDIAN_64_SIZE = sizeof(uint64_t);
56
57// Internal helper that writes the current buffer to the output. The
58// buffer position is reset to its initial value when this returns.
59static void GPBRefreshBuffer(GPBOutputBufferState *state) {
60  if (state->output == nil) {
61    // We're writing to a single buffer.
62    [NSException raise:@"OutOfSpace" format:@""];
63  }
64  if (state->position != 0) {
65    NSInteger written =
66        [state->output write:state->bytes maxLength:state->position];
67    if (written != (NSInteger)state->position) {
68      [NSException raise:@"WriteFailed" format:@""];
69    }
70    state->position = 0;
71  }
72}
73
74static void GPBWriteRawByte(GPBOutputBufferState *state, uint8_t value) {
75  if (state->position == state->size) {
76    GPBRefreshBuffer(state);
77  }
78  state->bytes[state->position++] = value;
79}
80
81static void GPBWriteRawVarint32(GPBOutputBufferState *state, int32_t value) {
82  while (YES) {
83    if ((value & ~0x7F) == 0) {
84      uint8_t val = (uint8_t)value;
85      GPBWriteRawByte(state, val);
86      return;
87    } else {
88      GPBWriteRawByte(state, (value & 0x7F) | 0x80);
89      value = GPBLogicalRightShift32(value, 7);
90    }
91  }
92}
93
94static void GPBWriteRawVarint64(GPBOutputBufferState *state, int64_t value) {
95  while (YES) {
96    if ((value & ~0x7FL) == 0) {
97      uint8_t val = (uint8_t)value;
98      GPBWriteRawByte(state, val);
99      return;
100    } else {
101      GPBWriteRawByte(state, ((int32_t)value & 0x7F) | 0x80);
102      value = GPBLogicalRightShift64(value, 7);
103    }
104  }
105}
106
107static void GPBWriteInt32NoTag(GPBOutputBufferState *state, int32_t value) {
108  if (value >= 0) {
109    GPBWriteRawVarint32(state, value);
110  } else {
111    // Must sign-extend
112    GPBWriteRawVarint64(state, value);
113  }
114}
115
116static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber,
117                           uint32_t value) {
118  GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint);
119  GPBWriteRawVarint32(state, value);
120}
121
122static void GPBWriteTagWithFormat(GPBOutputBufferState *state,
123                                  uint32_t fieldNumber, GPBWireFormat format) {
124  GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format));
125}
126
127static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state,
128                                      int32_t value) {
129  GPBWriteRawByte(state, (value)&0xFF);
130  GPBWriteRawByte(state, (value >> 8) & 0xFF);
131  GPBWriteRawByte(state, (value >> 16) & 0xFF);
132  GPBWriteRawByte(state, (value >> 24) & 0xFF);
133}
134
135static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
136                                      int64_t value) {
137  GPBWriteRawByte(state, (int32_t)(value)&0xFF);
138  GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF);
139  GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF);
140  GPBWriteRawByte(state, (int32_t)(value >> 24) & 0xFF);
141  GPBWriteRawByte(state, (int32_t)(value >> 32) & 0xFF);
142  GPBWriteRawByte(state, (int32_t)(value >> 40) & 0xFF);
143  GPBWriteRawByte(state, (int32_t)(value >> 48) & 0xFF);
144  GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF);
145}
146
147#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
148+ (void)load {
149  // This test exists to verify that CFStrings with embedded NULLs will work
150  // for us. If this Assert fails, all code below that depends on
151  // CFStringGetCStringPtr will NOT work properly on strings that contain
152  // embedded NULLs, and we do get that in some protobufs.
153  // Note that this will not be compiled in release.
154  // We didn't feel that just keeping it in a unit test was sufficient because
155  // the Protobuf unit tests are only run when somebody is actually working
156  // on protobufs.
157  CFStringRef zeroTest = CFSTR("Test\0String");
158  const char *cString = CFStringGetCStringPtr(zeroTest, kCFStringEncodingUTF8);
159  NSAssert(cString == NULL, @"Serious Error");
160}
161#endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
162
163- (void)dealloc {
164  [self flush];
165  [state_.output close];
166  [state_.output release];
167  [buffer_ release];
168
169  [super dealloc];
170}
171
172- (instancetype)initWithOutputStream:(NSOutputStream *)output {
173  NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
174  return [self initWithOutputStream:output data:data];
175}
176
177- (instancetype)initWithData:(NSMutableData *)data {
178  return [self initWithOutputStream:nil data:data];
179}
180
181// This initializer isn't exposed, but it is the designated initializer.
182// Setting OutputStream and NSData is to control the buffering behavior/size
183// of the work, but that is more obvious via the bufferSize: version.
184- (instancetype)initWithOutputStream:(NSOutputStream *)output
185                                data:(NSMutableData *)data {
186  if ((self = [super init])) {
187    buffer_ = [data retain];
188    [output open];
189    state_.bytes = [data mutableBytes];
190    state_.size = [data length];
191    state_.output = [output retain];
192  }
193  return self;
194}
195
196+ (instancetype)streamWithOutputStream:(NSOutputStream *)output {
197  NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
198  return [[[self alloc] initWithOutputStream:output
199                                        data:data] autorelease];
200}
201
202+ (instancetype)streamWithData:(NSMutableData *)data {
203  return [[[self alloc] initWithData:data] autorelease];
204}
205
206- (void)writeDoubleNoTag:(double)value {
207  GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
208}
209
210- (void)writeDouble:(int32_t)fieldNumber value:(double)value {
211  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
212  GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
213}
214
215- (void)writeFloatNoTag:(float)value {
216  GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
217}
218
219- (void)writeFloat:(int32_t)fieldNumber value:(float)value {
220  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
221  GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
222}
223
224- (void)writeUInt64NoTag:(uint64_t)value {
225  GPBWriteRawVarint64(&state_, value);
226}
227
228- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value {
229  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
230  GPBWriteRawVarint64(&state_, value);
231}
232
233- (void)writeInt64NoTag:(int64_t)value {
234  GPBWriteRawVarint64(&state_, value);
235}
236
237- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value {
238  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
239  GPBWriteRawVarint64(&state_, value);
240}
241
242- (void)writeInt32NoTag:(int32_t)value {
243  GPBWriteInt32NoTag(&state_, value);
244}
245
246- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value {
247  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
248  GPBWriteInt32NoTag(&state_, value);
249}
250
251- (void)writeFixed64NoTag:(uint64_t)value {
252  GPBWriteRawLittleEndian64(&state_, value);
253}
254
255- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value {
256  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
257  GPBWriteRawLittleEndian64(&state_, value);
258}
259
260- (void)writeFixed32NoTag:(uint32_t)value {
261  GPBWriteRawLittleEndian32(&state_, value);
262}
263
264- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value {
265  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
266  GPBWriteRawLittleEndian32(&state_, value);
267}
268
269- (void)writeBoolNoTag:(BOOL)value {
270  GPBWriteRawByte(&state_, (value ? 1 : 0));
271}
272
273- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value {
274  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
275  GPBWriteRawByte(&state_, (value ? 1 : 0));
276}
277
278- (void)writeStringNoTag:(const NSString *)value {
279  // If you are concerned about embedded NULLs see the test in
280  // +load above.
281  const char *quickString =
282      CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
283  size_t length = (quickString != NULL)
284                      ? strlen(quickString)
285                      : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
286  GPBWriteRawVarint32(&state_, (int32_t)length);
287
288  if (length == 0) {
289    return;
290  }
291
292  // Fast path: Most strings are short, if the buffer already has space,
293  // add to it directly.
294  NSUInteger bufferBytesLeft = state_.size - state_.position;
295  if (bufferBytesLeft >= length) {
296    NSUInteger usedBufferLength = 0;
297    BOOL result;
298    if (quickString != NULL) {
299      memcpy(state_.bytes + state_.position, quickString, length);
300      usedBufferLength = length;
301      result = YES;
302    } else {
303      result = [value getBytes:state_.bytes + state_.position
304                     maxLength:bufferBytesLeft
305                    usedLength:&usedBufferLength
306                      encoding:NSUTF8StringEncoding
307                       options:0
308                         range:NSMakeRange(0, [value length])
309                remainingRange:NULL];
310    }
311    if (result) {
312      NSAssert2((usedBufferLength == length),
313                @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength,
314                length);
315      state_.position += usedBufferLength;
316      return;
317    }
318  } else if (quickString != NULL) {
319    [self writeRawPtr:quickString offset:0 length:length];
320  } else {
321    // Slow path: just get it as data and write it out.
322    NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding];
323    NSAssert2(([utf8Data length] == length),
324              @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length],
325              length);
326    [self writeRawData:utf8Data];
327  }
328}
329
330- (void)writeString:(int32_t)fieldNumber value:(NSString *)value {
331  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
332  [self writeStringNoTag:value];
333}
334
335- (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value {
336  [value writeToCodedOutputStream:self];
337  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
338}
339
340- (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value {
341  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
342  [self writeGroupNoTag:fieldNumber value:value];
343}
344
345- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
346                         value:(const GPBUnknownFieldSet *)value {
347  [value writeToCodedOutputStream:self];
348  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
349}
350
351- (void)writeUnknownGroup:(int32_t)fieldNumber
352                    value:(GPBUnknownFieldSet *)value {
353  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
354  [self writeUnknownGroupNoTag:fieldNumber value:value];
355}
356
357- (void)writeMessageNoTag:(GPBMessage *)value {
358  GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]);
359  [value writeToCodedOutputStream:self];
360}
361
362- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value {
363  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
364  [self writeMessageNoTag:value];
365}
366
367- (void)writeBytesNoTag:(NSData *)value {
368  GPBWriteRawVarint32(&state_, (int32_t)[value length]);
369  [self writeRawData:value];
370}
371
372- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value {
373  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
374  [self writeBytesNoTag:value];
375}
376
377- (void)writeUInt32NoTag:(uint32_t)value {
378  GPBWriteRawVarint32(&state_, value);
379}
380
381- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value {
382  GPBWriteUInt32(&state_, fieldNumber, value);
383}
384
385- (void)writeEnumNoTag:(int32_t)value {
386  GPBWriteRawVarint32(&state_, value);
387}
388
389- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value {
390  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
391  GPBWriteRawVarint32(&state_, value);
392}
393
394- (void)writeSFixed32NoTag:(int32_t)value {
395  GPBWriteRawLittleEndian32(&state_, value);
396}
397
398- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value {
399  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
400  GPBWriteRawLittleEndian32(&state_, value);
401}
402
403- (void)writeSFixed64NoTag:(int64_t)value {
404  GPBWriteRawLittleEndian64(&state_, value);
405}
406
407- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value {
408  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
409  GPBWriteRawLittleEndian64(&state_, value);
410}
411
412- (void)writeSInt32NoTag:(int32_t)value {
413  GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
414}
415
416- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value {
417  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
418  GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
419}
420
421- (void)writeSInt64NoTag:(int64_t)value {
422  GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
423}
424
425- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value {
426  GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
427  GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
428}
429
430//%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME)
431//%- (void)write##NAME##Array:(int32_t)fieldNumber
432//%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
433//%       NAME$S        tag:(uint32_t)tag {
434//%  if (tag != 0) {
435//%    if (values.count == 0) return;
436//%    __block size_t dataSize = 0;
437//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
438//%#pragma unused(idx, stop)
439//%      dataSize += GPBCompute##NAME##SizeNoTag(value);
440//%    }];
441//%    GPBWriteRawVarint32(&state_, tag);
442//%    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
443//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
444//%#pragma unused(idx, stop)
445//%      [self write##NAME##NoTag:value];
446//%    }];
447//%  } else {
448//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
449//%#pragma unused(idx, stop)
450//%      [self write##NAME:fieldNumber value:value];
451//%    }];
452//%  }
453//%}
454//%
455//%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE)
456//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values {
457//%  for (TYPE *value in values) {
458//%    [self write##NAME:fieldNumber value:value];
459//%  }
460//%}
461//%
462//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, )
463// This block of code is generated, do not edit it directly.
464
465- (void)writeDoubleArray:(int32_t)fieldNumber
466                  values:(GPBDoubleArray *)values
467                     tag:(uint32_t)tag {
468  if (tag != 0) {
469    if (values.count == 0) return;
470    __block size_t dataSize = 0;
471    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
472#pragma unused(idx, stop)
473      dataSize += GPBComputeDoubleSizeNoTag(value);
474    }];
475    GPBWriteRawVarint32(&state_, tag);
476    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
477    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
478#pragma unused(idx, stop)
479      [self writeDoubleNoTag:value];
480    }];
481  } else {
482    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
483#pragma unused(idx, stop)
484      [self writeDouble:fieldNumber value:value];
485    }];
486  }
487}
488
489//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, )
490// This block of code is generated, do not edit it directly.
491
492- (void)writeFloatArray:(int32_t)fieldNumber
493                 values:(GPBFloatArray *)values
494                    tag:(uint32_t)tag {
495  if (tag != 0) {
496    if (values.count == 0) return;
497    __block size_t dataSize = 0;
498    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
499#pragma unused(idx, stop)
500      dataSize += GPBComputeFloatSizeNoTag(value);
501    }];
502    GPBWriteRawVarint32(&state_, tag);
503    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
504    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
505#pragma unused(idx, stop)
506      [self writeFloatNoTag:value];
507    }];
508  } else {
509    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
510#pragma unused(idx, stop)
511      [self writeFloat:fieldNumber value:value];
512    }];
513  }
514}
515
516//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, )
517// This block of code is generated, do not edit it directly.
518
519- (void)writeUInt64Array:(int32_t)fieldNumber
520                  values:(GPBUInt64Array *)values
521                     tag:(uint32_t)tag {
522  if (tag != 0) {
523    if (values.count == 0) return;
524    __block size_t dataSize = 0;
525    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
526#pragma unused(idx, stop)
527      dataSize += GPBComputeUInt64SizeNoTag(value);
528    }];
529    GPBWriteRawVarint32(&state_, tag);
530    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
531    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
532#pragma unused(idx, stop)
533      [self writeUInt64NoTag:value];
534    }];
535  } else {
536    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
537#pragma unused(idx, stop)
538      [self writeUInt64:fieldNumber value:value];
539    }];
540  }
541}
542
543//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, )
544// This block of code is generated, do not edit it directly.
545
546- (void)writeInt64Array:(int32_t)fieldNumber
547                 values:(GPBInt64Array *)values
548                    tag:(uint32_t)tag {
549  if (tag != 0) {
550    if (values.count == 0) return;
551    __block size_t dataSize = 0;
552    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
553#pragma unused(idx, stop)
554      dataSize += GPBComputeInt64SizeNoTag(value);
555    }];
556    GPBWriteRawVarint32(&state_, tag);
557    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
558    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
559#pragma unused(idx, stop)
560      [self writeInt64NoTag:value];
561    }];
562  } else {
563    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
564#pragma unused(idx, stop)
565      [self writeInt64:fieldNumber value:value];
566    }];
567  }
568}
569
570//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, )
571// This block of code is generated, do not edit it directly.
572
573- (void)writeInt32Array:(int32_t)fieldNumber
574                 values:(GPBInt32Array *)values
575                    tag:(uint32_t)tag {
576  if (tag != 0) {
577    if (values.count == 0) return;
578    __block size_t dataSize = 0;
579    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
580#pragma unused(idx, stop)
581      dataSize += GPBComputeInt32SizeNoTag(value);
582    }];
583    GPBWriteRawVarint32(&state_, tag);
584    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
585    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
586#pragma unused(idx, stop)
587      [self writeInt32NoTag:value];
588    }];
589  } else {
590    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
591#pragma unused(idx, stop)
592      [self writeInt32:fieldNumber value:value];
593    }];
594  }
595}
596
597//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, )
598// This block of code is generated, do not edit it directly.
599
600- (void)writeUInt32Array:(int32_t)fieldNumber
601                  values:(GPBUInt32Array *)values
602                     tag:(uint32_t)tag {
603  if (tag != 0) {
604    if (values.count == 0) return;
605    __block size_t dataSize = 0;
606    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
607#pragma unused(idx, stop)
608      dataSize += GPBComputeUInt32SizeNoTag(value);
609    }];
610    GPBWriteRawVarint32(&state_, tag);
611    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
612    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
613#pragma unused(idx, stop)
614      [self writeUInt32NoTag:value];
615    }];
616  } else {
617    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
618#pragma unused(idx, stop)
619      [self writeUInt32:fieldNumber value:value];
620    }];
621  }
622}
623
624//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, )
625// This block of code is generated, do not edit it directly.
626
627- (void)writeFixed64Array:(int32_t)fieldNumber
628                   values:(GPBUInt64Array *)values
629                      tag:(uint32_t)tag {
630  if (tag != 0) {
631    if (values.count == 0) return;
632    __block size_t dataSize = 0;
633    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
634#pragma unused(idx, stop)
635      dataSize += GPBComputeFixed64SizeNoTag(value);
636    }];
637    GPBWriteRawVarint32(&state_, tag);
638    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
639    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
640#pragma unused(idx, stop)
641      [self writeFixed64NoTag:value];
642    }];
643  } else {
644    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
645#pragma unused(idx, stop)
646      [self writeFixed64:fieldNumber value:value];
647    }];
648  }
649}
650
651//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, )
652// This block of code is generated, do not edit it directly.
653
654- (void)writeFixed32Array:(int32_t)fieldNumber
655                   values:(GPBUInt32Array *)values
656                      tag:(uint32_t)tag {
657  if (tag != 0) {
658    if (values.count == 0) return;
659    __block size_t dataSize = 0;
660    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
661#pragma unused(idx, stop)
662      dataSize += GPBComputeFixed32SizeNoTag(value);
663    }];
664    GPBWriteRawVarint32(&state_, tag);
665    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
666    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
667#pragma unused(idx, stop)
668      [self writeFixed32NoTag:value];
669    }];
670  } else {
671    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
672#pragma unused(idx, stop)
673      [self writeFixed32:fieldNumber value:value];
674    }];
675  }
676}
677
678//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, )
679// This block of code is generated, do not edit it directly.
680
681- (void)writeSInt32Array:(int32_t)fieldNumber
682                  values:(GPBInt32Array *)values
683                     tag:(uint32_t)tag {
684  if (tag != 0) {
685    if (values.count == 0) return;
686    __block size_t dataSize = 0;
687    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
688#pragma unused(idx, stop)
689      dataSize += GPBComputeSInt32SizeNoTag(value);
690    }];
691    GPBWriteRawVarint32(&state_, tag);
692    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
693    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
694#pragma unused(idx, stop)
695      [self writeSInt32NoTag:value];
696    }];
697  } else {
698    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
699#pragma unused(idx, stop)
700      [self writeSInt32:fieldNumber value:value];
701    }];
702  }
703}
704
705//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, )
706// This block of code is generated, do not edit it directly.
707
708- (void)writeSInt64Array:(int32_t)fieldNumber
709                  values:(GPBInt64Array *)values
710                     tag:(uint32_t)tag {
711  if (tag != 0) {
712    if (values.count == 0) return;
713    __block size_t dataSize = 0;
714    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
715#pragma unused(idx, stop)
716      dataSize += GPBComputeSInt64SizeNoTag(value);
717    }];
718    GPBWriteRawVarint32(&state_, tag);
719    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
720    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
721#pragma unused(idx, stop)
722      [self writeSInt64NoTag:value];
723    }];
724  } else {
725    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
726#pragma unused(idx, stop)
727      [self writeSInt64:fieldNumber value:value];
728    }];
729  }
730}
731
732//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, )
733// This block of code is generated, do not edit it directly.
734
735- (void)writeSFixed64Array:(int32_t)fieldNumber
736                    values:(GPBInt64Array *)values
737                       tag:(uint32_t)tag {
738  if (tag != 0) {
739    if (values.count == 0) return;
740    __block size_t dataSize = 0;
741    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
742#pragma unused(idx, stop)
743      dataSize += GPBComputeSFixed64SizeNoTag(value);
744    }];
745    GPBWriteRawVarint32(&state_, tag);
746    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
747    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
748#pragma unused(idx, stop)
749      [self writeSFixed64NoTag:value];
750    }];
751  } else {
752    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
753#pragma unused(idx, stop)
754      [self writeSFixed64:fieldNumber value:value];
755    }];
756  }
757}
758
759//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, )
760// This block of code is generated, do not edit it directly.
761
762- (void)writeSFixed32Array:(int32_t)fieldNumber
763                    values:(GPBInt32Array *)values
764                       tag:(uint32_t)tag {
765  if (tag != 0) {
766    if (values.count == 0) return;
767    __block size_t dataSize = 0;
768    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
769#pragma unused(idx, stop)
770      dataSize += GPBComputeSFixed32SizeNoTag(value);
771    }];
772    GPBWriteRawVarint32(&state_, tag);
773    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
774    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
775#pragma unused(idx, stop)
776      [self writeSFixed32NoTag:value];
777    }];
778  } else {
779    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
780#pragma unused(idx, stop)
781      [self writeSFixed32:fieldNumber value:value];
782    }];
783  }
784}
785
786//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, )
787// This block of code is generated, do not edit it directly.
788
789- (void)writeBoolArray:(int32_t)fieldNumber
790                values:(GPBBoolArray *)values
791                   tag:(uint32_t)tag {
792  if (tag != 0) {
793    if (values.count == 0) return;
794    __block size_t dataSize = 0;
795    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
796#pragma unused(idx, stop)
797      dataSize += GPBComputeBoolSizeNoTag(value);
798    }];
799    GPBWriteRawVarint32(&state_, tag);
800    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
801    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
802#pragma unused(idx, stop)
803      [self writeBoolNoTag:value];
804    }];
805  } else {
806    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
807#pragma unused(idx, stop)
808      [self writeBool:fieldNumber value:value];
809    }];
810  }
811}
812
813//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw)
814// This block of code is generated, do not edit it directly.
815
816- (void)writeEnumArray:(int32_t)fieldNumber
817                values:(GPBEnumArray *)values
818                   tag:(uint32_t)tag {
819  if (tag != 0) {
820    if (values.count == 0) return;
821    __block size_t dataSize = 0;
822    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
823#pragma unused(idx, stop)
824      dataSize += GPBComputeEnumSizeNoTag(value);
825    }];
826    GPBWriteRawVarint32(&state_, tag);
827    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
828    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
829#pragma unused(idx, stop)
830      [self writeEnumNoTag:value];
831    }];
832  } else {
833    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
834#pragma unused(idx, stop)
835      [self writeEnum:fieldNumber value:value];
836    }];
837  }
838}
839
840//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString)
841// This block of code is generated, do not edit it directly.
842
843- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values {
844  for (NSString *value in values) {
845    [self writeString:fieldNumber value:value];
846  }
847}
848
849//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage)
850// This block of code is generated, do not edit it directly.
851
852- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values {
853  for (GPBMessage *value in values) {
854    [self writeMessage:fieldNumber value:value];
855  }
856}
857
858//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData)
859// This block of code is generated, do not edit it directly.
860
861- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values {
862  for (NSData *value in values) {
863    [self writeBytes:fieldNumber value:value];
864  }
865}
866
867//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage)
868// This block of code is generated, do not edit it directly.
869
870- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
871  for (GPBMessage *value in values) {
872    [self writeGroup:fieldNumber value:value];
873  }
874}
875
876//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet)
877// This block of code is generated, do not edit it directly.
878
879- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
880  for (GPBUnknownFieldSet *value in values) {
881    [self writeUnknownGroup:fieldNumber value:value];
882  }
883}
884
885//%PDDM-EXPAND-END (19 expansions)
886
887- (void)writeMessageSetExtension:(int32_t)fieldNumber
888                           value:(GPBMessage *)value {
889  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
890                        GPBWireFormatStartGroup);
891  GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
892  [self writeMessage:GPBWireFormatMessageSetMessage value:value];
893  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
894                        GPBWireFormatEndGroup);
895}
896
897- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value {
898  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
899                        GPBWireFormatStartGroup);
900  GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
901  [self writeBytes:GPBWireFormatMessageSetMessage value:value];
902  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
903                        GPBWireFormatEndGroup);
904}
905
906- (void)flush {
907  if (state_.output != nil) {
908    GPBRefreshBuffer(&state_);
909  }
910}
911
912- (void)writeRawByte:(uint8_t)value {
913  GPBWriteRawByte(&state_, value);
914}
915
916- (void)writeRawData:(const NSData *)data {
917  [self writeRawPtr:[data bytes] offset:0 length:[data length]];
918}
919
920- (void)writeRawPtr:(const void *)value
921             offset:(size_t)offset
922             length:(size_t)length {
923  if (value == nil || length == 0) {
924    return;
925  }
926
927  NSUInteger bufferLength = state_.size;
928  NSUInteger bufferBytesLeft = bufferLength - state_.position;
929  if (bufferBytesLeft >= length) {
930    // We have room in the current buffer.
931    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, length);
932    state_.position += length;
933  } else {
934    // Write extends past current buffer.  Fill the rest of this buffer and
935    // flush.
936    size_t bytesWritten = bufferBytesLeft;
937    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset,
938           bytesWritten);
939    offset += bytesWritten;
940    length -= bytesWritten;
941    state_.position = bufferLength;
942    GPBRefreshBuffer(&state_);
943    bufferLength = state_.size;
944
945    // Now deal with the rest.
946    // Since we have an output stream, this is our buffer
947    // and buffer offset == 0
948    if (length <= bufferLength) {
949      // Fits in new buffer.
950      memcpy(state_.bytes, ((uint8_t *)value) + offset, length);
951      state_.position = length;
952    } else {
953      // Write is very big.  Let's do it all at once.
954      [state_.output write:((uint8_t *)value) + offset maxLength:length];
955    }
956  }
957}
958
959- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format {
960  GPBWriteTagWithFormat(&state_, fieldNumber, format);
961}
962
963- (void)writeRawVarint32:(int32_t)value {
964  GPBWriteRawVarint32(&state_, value);
965}
966
967- (void)writeRawVarintSizeTAs32:(size_t)value {
968  // Note the truncation.
969  GPBWriteRawVarint32(&state_, (int32_t)value);
970}
971
972- (void)writeRawVarint64:(int64_t)value {
973  GPBWriteRawVarint64(&state_, value);
974}
975
976- (void)writeRawLittleEndian32:(int32_t)value {
977  GPBWriteRawLittleEndian32(&state_, value);
978}
979
980- (void)writeRawLittleEndian64:(int64_t)value {
981  GPBWriteRawLittleEndian64(&state_, value);
982}
983
984@end
985
986size_t GPBComputeDoubleSizeNoTag(Float64 value) {
987#pragma unused(value)
988  return LITTLE_ENDIAN_64_SIZE;
989}
990
991size_t GPBComputeFloatSizeNoTag(Float32 value) {
992#pragma unused(value)
993  return LITTLE_ENDIAN_32_SIZE;
994}
995
996size_t GPBComputeUInt64SizeNoTag(uint64_t value) {
997  return GPBComputeRawVarint64Size(value);
998}
999
1000size_t GPBComputeInt64SizeNoTag(int64_t value) {
1001  return GPBComputeRawVarint64Size(value);
1002}
1003
1004size_t GPBComputeInt32SizeNoTag(int32_t value) {
1005  if (value >= 0) {
1006    return GPBComputeRawVarint32Size(value);
1007  } else {
1008    // Must sign-extend.
1009    return 10;
1010  }
1011}
1012
1013size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) {
1014  return GPBComputeInt32SizeNoTag((int32_t)value);
1015}
1016
1017size_t GPBComputeFixed64SizeNoTag(uint64_t value) {
1018#pragma unused(value)
1019  return LITTLE_ENDIAN_64_SIZE;
1020}
1021
1022size_t GPBComputeFixed32SizeNoTag(uint32_t value) {
1023#pragma unused(value)
1024  return LITTLE_ENDIAN_32_SIZE;
1025}
1026
1027size_t GPBComputeBoolSizeNoTag(BOOL value) {
1028#pragma unused(value)
1029  return 1;
1030}
1031
1032size_t GPBComputeStringSizeNoTag(NSString *value) {
1033  // If you are concerned about embedded NULLs see the test in
1034  // +load above.
1035  const char *quickString =
1036      CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
1037  NSUInteger length =
1038      (quickString != NULL)
1039          ? strlen(quickString)
1040          : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
1041  return GPBComputeRawVarint32SizeForInteger(length) + length;
1042}
1043
1044size_t GPBComputeGroupSizeNoTag(GPBMessage *value) {
1045  return [value serializedSize];
1046}
1047
1048size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) {
1049  return value.serializedSize;
1050}
1051
1052size_t GPBComputeMessageSizeNoTag(GPBMessage *value) {
1053  size_t size = [value serializedSize];
1054  return GPBComputeRawVarint32SizeForInteger(size) + size;
1055}
1056
1057size_t GPBComputeBytesSizeNoTag(NSData *value) {
1058  NSUInteger valueLength = [value length];
1059  return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength;
1060}
1061
1062size_t GPBComputeUInt32SizeNoTag(int32_t value) {
1063  return GPBComputeRawVarint32Size(value);
1064}
1065
1066size_t GPBComputeEnumSizeNoTag(int32_t value) {
1067  return GPBComputeRawVarint32Size(value);
1068}
1069
1070size_t GPBComputeSFixed32SizeNoTag(int32_t value) {
1071#pragma unused(value)
1072  return LITTLE_ENDIAN_32_SIZE;
1073}
1074
1075size_t GPBComputeSFixed64SizeNoTag(int64_t value) {
1076#pragma unused(value)
1077  return LITTLE_ENDIAN_64_SIZE;
1078}
1079
1080size_t GPBComputeSInt32SizeNoTag(int32_t value) {
1081  return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value));
1082}
1083
1084size_t GPBComputeSInt64SizeNoTag(int64_t value) {
1085  return GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
1086}
1087
1088size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) {
1089  return GPBComputeTagSize(fieldNumber) + GPBComputeDoubleSizeNoTag(value);
1090}
1091
1092size_t GPBComputeFloatSize(int32_t fieldNumber, float value) {
1093  return GPBComputeTagSize(fieldNumber) + GPBComputeFloatSizeNoTag(value);
1094}
1095
1096size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) {
1097  return GPBComputeTagSize(fieldNumber) + GPBComputeUInt64SizeNoTag(value);
1098}
1099
1100size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) {
1101  return GPBComputeTagSize(fieldNumber) + GPBComputeInt64SizeNoTag(value);
1102}
1103
1104size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) {
1105  return GPBComputeTagSize(fieldNumber) + GPBComputeInt32SizeNoTag(value);
1106}
1107
1108size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) {
1109  return GPBComputeTagSize(fieldNumber) + GPBComputeFixed64SizeNoTag(value);
1110}
1111
1112size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) {
1113  return GPBComputeTagSize(fieldNumber) + GPBComputeFixed32SizeNoTag(value);
1114}
1115
1116size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) {
1117  return GPBComputeTagSize(fieldNumber) + GPBComputeBoolSizeNoTag(value);
1118}
1119
1120size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) {
1121  return GPBComputeTagSize(fieldNumber) + GPBComputeStringSizeNoTag(value);
1122}
1123
1124size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) {
1125  return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value);
1126}
1127
1128size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
1129                                  GPBUnknownFieldSet *value) {
1130  return GPBComputeTagSize(fieldNumber) * 2 +
1131         GPBComputeUnknownGroupSizeNoTag(value);
1132}
1133
1134size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) {
1135  return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value);
1136}
1137
1138size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) {
1139  return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value);
1140}
1141
1142size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) {
1143  return GPBComputeTagSize(fieldNumber) + GPBComputeUInt32SizeNoTag(value);
1144}
1145
1146size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) {
1147  return GPBComputeTagSize(fieldNumber) + GPBComputeEnumSizeNoTag(value);
1148}
1149
1150size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) {
1151  return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed32SizeNoTag(value);
1152}
1153
1154size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) {
1155  return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed64SizeNoTag(value);
1156}
1157
1158size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) {
1159  return GPBComputeTagSize(fieldNumber) + GPBComputeSInt32SizeNoTag(value);
1160}
1161
1162size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) {
1163  return GPBComputeTagSize(fieldNumber) +
1164         GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
1165}
1166
1167size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber,
1168                                         GPBMessage *value) {
1169  return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
1170         GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
1171         GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value);
1172}
1173
1174size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber,
1175                                            NSData *value) {
1176  return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
1177         GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
1178         GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value);
1179}
1180
1181size_t GPBComputeTagSize(int32_t fieldNumber) {
1182  return GPBComputeRawVarint32Size(
1183      GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
1184}
1185
1186size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) {
1187  size_t result = GPBComputeTagSize(field_number);
1188  if (dataType == GPBDataTypeGroup) {
1189    // Groups have both a start and an end tag.
1190    return result * 2;
1191  } else {
1192    return result;
1193  }
1194}
1195
1196size_t GPBComputeRawVarint32Size(int32_t value) {
1197  // value is treated as unsigned, so it won't be sign-extended if negative.
1198  if ((value & (0xffffffff << 7)) == 0) return 1;
1199  if ((value & (0xffffffff << 14)) == 0) return 2;
1200  if ((value & (0xffffffff << 21)) == 0) return 3;
1201  if ((value & (0xffffffff << 28)) == 0) return 4;
1202  return 5;
1203}
1204
1205size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) {
1206  // Note the truncation.
1207  return GPBComputeRawVarint32Size((int32_t)value);
1208}
1209
1210size_t GPBComputeRawVarint64Size(int64_t value) {
1211  if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
1212  if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
1213  if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
1214  if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
1215  if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
1216  if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
1217  if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
1218  if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
1219  if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
1220  return 10;
1221}
1222