blob: fdb695ece61d274ea9cae4045ecc57e78872aaa0 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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 "GPBMessage_PackagePrivate.h"
32
33#import <objc/runtime.h>
34#import <objc/message.h>
35
36#import "GPBArray_PackagePrivate.h"
37#import "GPBCodedInputStream_PackagePrivate.h"
38#import "GPBCodedOutputStream.h"
39#import "GPBDescriptor_PackagePrivate.h"
40#import "GPBDictionary_PackagePrivate.h"
41#import "GPBExtensionInternals.h"
42#import "GPBExtensionRegistry.h"
43#import "GPBRootObject_PackagePrivate.h"
44#import "GPBUnknownFieldSet_PackagePrivate.h"
45#import "GPBUtilities_PackagePrivate.h"
46
47NSString *const GPBMessageErrorDomain =
48 GPBNSStringifySymbol(GPBMessageErrorDomain);
49
50#ifdef DEBUG
51NSString *const GPBExceptionMessageKey =
52 GPBNSStringifySymbol(GPBExceptionMessage);
53#endif // DEBUG
54
55static NSString *const kGPBDataCoderKey = @"GPBData";
56
57#ifndef _GPBCompileAssert
58 #if __has_feature(c_static_assert) || __has_extension(c_static_assert)
59 #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg)
60 #else
61 // Pre-Xcode 7 support.
62 #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg
63 #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg)
64 #define _GPBCompileAssert(test, msg) \
65 typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
66 #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert)
67#endif // _GPBCompileAssert
68
69//
70// PLEASE REMEMBER:
71//
72// This is the base class for *all* messages generated, so any selector defined,
73// *public* or *private* could end up colliding with a proto message field. So
74// avoid using selectors that could match a property, use C functions to hide
75// them, etc.
76//
77
78@interface GPBMessage () {
79 @package
80 GPBUnknownFieldSet *unknownFields_;
81 NSMutableDictionary *extensionMap_;
82 NSMutableDictionary *autocreatedExtensionMap_;
83
84 // If the object was autocreated, we remember the creator so that if we get
85 // mutated, we can inform the creator to make our field visible.
86 GPBMessage *autocreator_;
87 GPBFieldDescriptor *autocreatorField_;
88 GPBExtensionDescriptor *autocreatorExtension_;
89}
90@end
91
92static id CreateArrayForField(GPBFieldDescriptor *field,
93 GPBMessage *autocreator)
94 __attribute__((ns_returns_retained));
95static id GetOrCreateArrayIvarWithField(GPBMessage *self,
96 GPBFieldDescriptor *field,
97 GPBFileSyntax syntax);
98static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
99static id CreateMapForField(GPBFieldDescriptor *field,
100 GPBMessage *autocreator)
101 __attribute__((ns_returns_retained));
102static id GetOrCreateMapIvarWithField(GPBMessage *self,
103 GPBFieldDescriptor *field,
104 GPBFileSyntax syntax);
105static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
106static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
107 NSZone *zone)
108 __attribute__((ns_returns_retained));
109
110static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
111 return [NSError errorWithDomain:GPBMessageErrorDomain
112 code:code
113 userInfo:userInfo];
114}
115
116static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) {
117 NSDictionary *userInfo = nil;
118 if ([reason length]) {
119 userInfo = @{ @"Reason" : reason };
120 }
121 return MessageError(code, userInfo);
122}
123
124
125static void CheckExtension(GPBMessage *self,
126 GPBExtensionDescriptor *extension) {
127 if ([self class] != extension.containingMessageClass) {
128 [NSException
129 raise:NSInvalidArgumentException
130 format:@"Extension %@ used on wrong class (%@ instead of %@)",
131 extension.singletonName,
132 [self class], extension.containingMessageClass];
133 }
134}
135
136static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
137 NSZone *zone) {
138 if (extensionMap.count == 0) {
139 return nil;
140 }
141 NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
142 initWithCapacity:extensionMap.count];
143
144 for (GPBExtensionDescriptor *extension in extensionMap) {
145 id value = [extensionMap objectForKey:extension];
146 BOOL isMessageExtension = GPBExtensionIsMessage(extension);
147
148 if (extension.repeated) {
149 if (isMessageExtension) {
150 NSMutableArray *list =
151 [[NSMutableArray alloc] initWithCapacity:[value count]];
152 for (GPBMessage *listValue in value) {
153 GPBMessage *copiedValue = [listValue copyWithZone:zone];
154 [list addObject:copiedValue];
155 [copiedValue release];
156 }
157 [result setObject:list forKey:extension];
158 [list release];
159 } else {
160 NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
161 [result setObject:copiedValue forKey:extension];
162 [copiedValue release];
163 }
164 } else {
165 if (isMessageExtension) {
166 GPBMessage *copiedValue = [value copyWithZone:zone];
167 [result setObject:copiedValue forKey:extension];
168 [copiedValue release];
169 } else {
170 [result setObject:value forKey:extension];
171 }
172 }
173 }
174
175 return result;
176}
177
178static id CreateArrayForField(GPBFieldDescriptor *field,
179 GPBMessage *autocreator) {
180 id result;
181 GPBDataType fieldDataType = GPBGetFieldDataType(field);
182 switch (fieldDataType) {
183 case GPBDataTypeBool:
184 result = [[GPBBoolArray alloc] init];
185 break;
186 case GPBDataTypeFixed32:
187 case GPBDataTypeUInt32:
188 result = [[GPBUInt32Array alloc] init];
189 break;
190 case GPBDataTypeInt32:
191 case GPBDataTypeSFixed32:
192 case GPBDataTypeSInt32:
193 result = [[GPBInt32Array alloc] init];
194 break;
195 case GPBDataTypeFixed64:
196 case GPBDataTypeUInt64:
197 result = [[GPBUInt64Array alloc] init];
198 break;
199 case GPBDataTypeInt64:
200 case GPBDataTypeSFixed64:
201 case GPBDataTypeSInt64:
202 result = [[GPBInt64Array alloc] init];
203 break;
204 case GPBDataTypeFloat:
205 result = [[GPBFloatArray alloc] init];
206 break;
207 case GPBDataTypeDouble:
208 result = [[GPBDoubleArray alloc] init];
209 break;
210
211 case GPBDataTypeEnum:
212 result = [[GPBEnumArray alloc]
213 initWithValidationFunction:field.enumDescriptor.enumVerifier];
214 break;
215
216 case GPBDataTypeBytes:
217 case GPBDataTypeGroup:
218 case GPBDataTypeMessage:
219 case GPBDataTypeString:
220 if (autocreator) {
221 result = [[GPBAutocreatedArray alloc] init];
222 } else {
223 result = [[NSMutableArray alloc] init];
224 }
225 break;
226 }
227
228 if (autocreator) {
229 if (GPBDataTypeIsObject(fieldDataType)) {
230 GPBAutocreatedArray *autoArray = result;
231 autoArray->_autocreator = autocreator;
232 } else {
233 GPBInt32Array *gpbArray = result;
234 gpbArray->_autocreator = autocreator;
235 }
236 }
237
238 return result;
239}
240
241static id CreateMapForField(GPBFieldDescriptor *field,
242 GPBMessage *autocreator) {
243 id result;
244 GPBDataType keyDataType = field.mapKeyDataType;
245 GPBDataType valueDataType = GPBGetFieldDataType(field);
246 switch (keyDataType) {
247 case GPBDataTypeBool:
248 switch (valueDataType) {
249 case GPBDataTypeBool:
250 result = [[GPBBoolBoolDictionary alloc] init];
251 break;
252 case GPBDataTypeFixed32:
253 case GPBDataTypeUInt32:
254 result = [[GPBBoolUInt32Dictionary alloc] init];
255 break;
256 case GPBDataTypeInt32:
257 case GPBDataTypeSFixed32:
258 case GPBDataTypeSInt32:
259 result = [[GPBBoolInt32Dictionary alloc] init];
260 break;
261 case GPBDataTypeFixed64:
262 case GPBDataTypeUInt64:
263 result = [[GPBBoolUInt64Dictionary alloc] init];
264 break;
265 case GPBDataTypeInt64:
266 case GPBDataTypeSFixed64:
267 case GPBDataTypeSInt64:
268 result = [[GPBBoolInt64Dictionary alloc] init];
269 break;
270 case GPBDataTypeFloat:
271 result = [[GPBBoolFloatDictionary alloc] init];
272 break;
273 case GPBDataTypeDouble:
274 result = [[GPBBoolDoubleDictionary alloc] init];
275 break;
276 case GPBDataTypeEnum:
277 result = [[GPBBoolEnumDictionary alloc]
278 initWithValidationFunction:field.enumDescriptor.enumVerifier];
279 break;
280 case GPBDataTypeBytes:
281 case GPBDataTypeMessage:
282 case GPBDataTypeString:
283 result = [[GPBBoolObjectDictionary alloc] init];
284 break;
285 case GPBDataTypeGroup:
286 NSCAssert(NO, @"shouldn't happen");
287 return nil;
288 }
289 break;
290 case GPBDataTypeFixed32:
291 case GPBDataTypeUInt32:
292 switch (valueDataType) {
293 case GPBDataTypeBool:
294 result = [[GPBUInt32BoolDictionary alloc] init];
295 break;
296 case GPBDataTypeFixed32:
297 case GPBDataTypeUInt32:
298 result = [[GPBUInt32UInt32Dictionary alloc] init];
299 break;
300 case GPBDataTypeInt32:
301 case GPBDataTypeSFixed32:
302 case GPBDataTypeSInt32:
303 result = [[GPBUInt32Int32Dictionary alloc] init];
304 break;
305 case GPBDataTypeFixed64:
306 case GPBDataTypeUInt64:
307 result = [[GPBUInt32UInt64Dictionary alloc] init];
308 break;
309 case GPBDataTypeInt64:
310 case GPBDataTypeSFixed64:
311 case GPBDataTypeSInt64:
312 result = [[GPBUInt32Int64Dictionary alloc] init];
313 break;
314 case GPBDataTypeFloat:
315 result = [[GPBUInt32FloatDictionary alloc] init];
316 break;
317 case GPBDataTypeDouble:
318 result = [[GPBUInt32DoubleDictionary alloc] init];
319 break;
320 case GPBDataTypeEnum:
321 result = [[GPBUInt32EnumDictionary alloc]
322 initWithValidationFunction:field.enumDescriptor.enumVerifier];
323 break;
324 case GPBDataTypeBytes:
325 case GPBDataTypeMessage:
326 case GPBDataTypeString:
327 result = [[GPBUInt32ObjectDictionary alloc] init];
328 break;
329 case GPBDataTypeGroup:
330 NSCAssert(NO, @"shouldn't happen");
331 return nil;
332 }
333 break;
334 case GPBDataTypeInt32:
335 case GPBDataTypeSFixed32:
336 case GPBDataTypeSInt32:
337 switch (valueDataType) {
338 case GPBDataTypeBool:
339 result = [[GPBInt32BoolDictionary alloc] init];
340 break;
341 case GPBDataTypeFixed32:
342 case GPBDataTypeUInt32:
343 result = [[GPBInt32UInt32Dictionary alloc] init];
344 break;
345 case GPBDataTypeInt32:
346 case GPBDataTypeSFixed32:
347 case GPBDataTypeSInt32:
348 result = [[GPBInt32Int32Dictionary alloc] init];
349 break;
350 case GPBDataTypeFixed64:
351 case GPBDataTypeUInt64:
352 result = [[GPBInt32UInt64Dictionary alloc] init];
353 break;
354 case GPBDataTypeInt64:
355 case GPBDataTypeSFixed64:
356 case GPBDataTypeSInt64:
357 result = [[GPBInt32Int64Dictionary alloc] init];
358 break;
359 case GPBDataTypeFloat:
360 result = [[GPBInt32FloatDictionary alloc] init];
361 break;
362 case GPBDataTypeDouble:
363 result = [[GPBInt32DoubleDictionary alloc] init];
364 break;
365 case GPBDataTypeEnum:
366 result = [[GPBInt32EnumDictionary alloc]
367 initWithValidationFunction:field.enumDescriptor.enumVerifier];
368 break;
369 case GPBDataTypeBytes:
370 case GPBDataTypeMessage:
371 case GPBDataTypeString:
372 result = [[GPBInt32ObjectDictionary alloc] init];
373 break;
374 case GPBDataTypeGroup:
375 NSCAssert(NO, @"shouldn't happen");
376 return nil;
377 }
378 break;
379 case GPBDataTypeFixed64:
380 case GPBDataTypeUInt64:
381 switch (valueDataType) {
382 case GPBDataTypeBool:
383 result = [[GPBUInt64BoolDictionary alloc] init];
384 break;
385 case GPBDataTypeFixed32:
386 case GPBDataTypeUInt32:
387 result = [[GPBUInt64UInt32Dictionary alloc] init];
388 break;
389 case GPBDataTypeInt32:
390 case GPBDataTypeSFixed32:
391 case GPBDataTypeSInt32:
392 result = [[GPBUInt64Int32Dictionary alloc] init];
393 break;
394 case GPBDataTypeFixed64:
395 case GPBDataTypeUInt64:
396 result = [[GPBUInt64UInt64Dictionary alloc] init];
397 break;
398 case GPBDataTypeInt64:
399 case GPBDataTypeSFixed64:
400 case GPBDataTypeSInt64:
401 result = [[GPBUInt64Int64Dictionary alloc] init];
402 break;
403 case GPBDataTypeFloat:
404 result = [[GPBUInt64FloatDictionary alloc] init];
405 break;
406 case GPBDataTypeDouble:
407 result = [[GPBUInt64DoubleDictionary alloc] init];
408 break;
409 case GPBDataTypeEnum:
410 result = [[GPBUInt64EnumDictionary alloc]
411 initWithValidationFunction:field.enumDescriptor.enumVerifier];
412 break;
413 case GPBDataTypeBytes:
414 case GPBDataTypeMessage:
415 case GPBDataTypeString:
416 result = [[GPBUInt64ObjectDictionary alloc] init];
417 break;
418 case GPBDataTypeGroup:
419 NSCAssert(NO, @"shouldn't happen");
420 return nil;
421 }
422 break;
423 case GPBDataTypeInt64:
424 case GPBDataTypeSFixed64:
425 case GPBDataTypeSInt64:
426 switch (valueDataType) {
427 case GPBDataTypeBool:
428 result = [[GPBInt64BoolDictionary alloc] init];
429 break;
430 case GPBDataTypeFixed32:
431 case GPBDataTypeUInt32:
432 result = [[GPBInt64UInt32Dictionary alloc] init];
433 break;
434 case GPBDataTypeInt32:
435 case GPBDataTypeSFixed32:
436 case GPBDataTypeSInt32:
437 result = [[GPBInt64Int32Dictionary alloc] init];
438 break;
439 case GPBDataTypeFixed64:
440 case GPBDataTypeUInt64:
441 result = [[GPBInt64UInt64Dictionary alloc] init];
442 break;
443 case GPBDataTypeInt64:
444 case GPBDataTypeSFixed64:
445 case GPBDataTypeSInt64:
446 result = [[GPBInt64Int64Dictionary alloc] init];
447 break;
448 case GPBDataTypeFloat:
449 result = [[GPBInt64FloatDictionary alloc] init];
450 break;
451 case GPBDataTypeDouble:
452 result = [[GPBInt64DoubleDictionary alloc] init];
453 break;
454 case GPBDataTypeEnum:
455 result = [[GPBInt64EnumDictionary alloc]
456 initWithValidationFunction:field.enumDescriptor.enumVerifier];
457 break;
458 case GPBDataTypeBytes:
459 case GPBDataTypeMessage:
460 case GPBDataTypeString:
461 result = [[GPBInt64ObjectDictionary alloc] init];
462 break;
463 case GPBDataTypeGroup:
464 NSCAssert(NO, @"shouldn't happen");
465 return nil;
466 }
467 break;
468 case GPBDataTypeString:
469 switch (valueDataType) {
470 case GPBDataTypeBool:
471 result = [[GPBStringBoolDictionary alloc] init];
472 break;
473 case GPBDataTypeFixed32:
474 case GPBDataTypeUInt32:
475 result = [[GPBStringUInt32Dictionary alloc] init];
476 break;
477 case GPBDataTypeInt32:
478 case GPBDataTypeSFixed32:
479 case GPBDataTypeSInt32:
480 result = [[GPBStringInt32Dictionary alloc] init];
481 break;
482 case GPBDataTypeFixed64:
483 case GPBDataTypeUInt64:
484 result = [[GPBStringUInt64Dictionary alloc] init];
485 break;
486 case GPBDataTypeInt64:
487 case GPBDataTypeSFixed64:
488 case GPBDataTypeSInt64:
489 result = [[GPBStringInt64Dictionary alloc] init];
490 break;
491 case GPBDataTypeFloat:
492 result = [[GPBStringFloatDictionary alloc] init];
493 break;
494 case GPBDataTypeDouble:
495 result = [[GPBStringDoubleDictionary alloc] init];
496 break;
497 case GPBDataTypeEnum:
498 result = [[GPBStringEnumDictionary alloc]
499 initWithValidationFunction:field.enumDescriptor.enumVerifier];
500 break;
501 case GPBDataTypeBytes:
502 case GPBDataTypeMessage:
503 case GPBDataTypeString:
504 if (autocreator) {
505 result = [[GPBAutocreatedDictionary alloc] init];
506 } else {
507 result = [[NSMutableDictionary alloc] init];
508 }
509 break;
510 case GPBDataTypeGroup:
511 NSCAssert(NO, @"shouldn't happen");
512 return nil;
513 }
514 break;
515
516 case GPBDataTypeFloat:
517 case GPBDataTypeDouble:
518 case GPBDataTypeEnum:
519 case GPBDataTypeBytes:
520 case GPBDataTypeGroup:
521 case GPBDataTypeMessage:
522 NSCAssert(NO, @"shouldn't happen");
523 return nil;
524 }
525
526 if (autocreator) {
527 if ((keyDataType == GPBDataTypeString) &&
528 GPBDataTypeIsObject(valueDataType)) {
529 GPBAutocreatedDictionary *autoDict = result;
530 autoDict->_autocreator = autocreator;
531 } else {
532 GPBInt32Int32Dictionary *gpbDict = result;
533 gpbDict->_autocreator = autocreator;
534 }
535 }
536
537 return result;
538}
539
540#if !defined(__clang_analyzer__)
541// These functions are blocked from the analyzer because the analyzer sees the
542// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
543// so use of the array/map after the call returns is flagged as a use after
544// free.
545// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
546// count be holding onto the object (it is transfering it), the object is
547// still valid after returning from the call. The other way to avoid this
548// would be to add a -retain/-autorelease, but that would force every
549// repeated/map field parsed into the autorelease pool which is both a memory
550// and performance hit.
551
552static id GetOrCreateArrayIvarWithField(GPBMessage *self,
553 GPBFieldDescriptor *field,
554 GPBFileSyntax syntax) {
555 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
556 if (!array) {
557 // No lock needed, this is called from places expecting to mutate
558 // so no threading protection is needed.
559 array = CreateArrayForField(field, nil);
560 GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
561 }
562 return array;
563}
564
565// This is like GPBGetObjectIvarWithField(), but for arrays, it should
566// only be used to wire the method into the class.
567static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
568 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
569 if (!array) {
570 // Check again after getting the lock.
571 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
572 array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
573 if (!array) {
574 array = CreateArrayForField(field, self);
575 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
576 }
577 dispatch_semaphore_signal(self->readOnlySemaphore_);
578 }
579 return array;
580}
581
582static id GetOrCreateMapIvarWithField(GPBMessage *self,
583 GPBFieldDescriptor *field,
584 GPBFileSyntax syntax) {
585 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
586 if (!dict) {
587 // No lock needed, this is called from places expecting to mutate
588 // so no threading protection is needed.
589 dict = CreateMapForField(field, nil);
590 GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
591 }
592 return dict;
593}
594
595// This is like GPBGetObjectIvarWithField(), but for maps, it should
596// only be used to wire the method into the class.
597static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
598 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
599 if (!dict) {
600 // Check again after getting the lock.
601 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
602 dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
603 if (!dict) {
604 dict = CreateMapForField(field, self);
605 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict);
606 }
607 dispatch_semaphore_signal(self->readOnlySemaphore_);
608 }
609 return dict;
610}
611
612#endif // !defined(__clang_analyzer__)
613
614GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
615 GPBMessage *autocreator,
616 GPBFieldDescriptor *field) {
617 GPBMessage *message = [[msgClass alloc] init];
618 message->autocreator_ = autocreator;
619 message->autocreatorField_ = [field retain];
620 return message;
621}
622
623static GPBMessage *CreateMessageWithAutocreatorForExtension(
624 Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension)
625 __attribute__((ns_returns_retained));
626
627static GPBMessage *CreateMessageWithAutocreatorForExtension(
628 Class msgClass, GPBMessage *autocreator,
629 GPBExtensionDescriptor *extension) {
630 GPBMessage *message = [[msgClass alloc] init];
631 message->autocreator_ = autocreator;
632 message->autocreatorExtension_ = [extension retain];
633 return message;
634}
635
636BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) {
637 return (message->autocreator_ == parent);
638}
639
640void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
641 // Message objects that are implicitly created by accessing a message field
642 // are initially not visible via the hasX selector. This method makes them
643 // visible.
644 if (self->autocreator_) {
645 // This will recursively make all parent messages visible until it reaches a
646 // super-creator that's visible.
647 if (self->autocreatorField_) {
648 GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
649 GPBSetObjectIvarWithFieldInternal(self->autocreator_,
650 self->autocreatorField_, self, syntax);
651 } else {
652 [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
653 }
654 }
655}
656
657void GPBAutocreatedArrayModified(GPBMessage *self, id array) {
658 // When one of our autocreated arrays adds elements, make it visible.
659 GPBDescriptor *descriptor = [[self class] descriptor];
660 for (GPBFieldDescriptor *field in descriptor->fields_) {
661 if (field.fieldType == GPBFieldTypeRepeated) {
662 id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
663 if (curArray == array) {
664 if (GPBFieldDataTypeIsObject(field)) {
665 GPBAutocreatedArray *autoArray = array;
666 autoArray->_autocreator = nil;
667 } else {
668 GPBInt32Array *gpbArray = array;
669 gpbArray->_autocreator = nil;
670 }
671 GPBBecomeVisibleToAutocreator(self);
672 return;
673 }
674 }
675 }
676 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self);
677}
678
679void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) {
680 // When one of our autocreated dicts adds elements, make it visible.
681 GPBDescriptor *descriptor = [[self class] descriptor];
682 for (GPBFieldDescriptor *field in descriptor->fields_) {
683 if (field.fieldType == GPBFieldTypeMap) {
684 id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
685 if (curDict == dictionary) {
686 if ((field.mapKeyDataType == GPBDataTypeString) &&
687 GPBFieldDataTypeIsObject(field)) {
688 GPBAutocreatedDictionary *autoDict = dictionary;
689 autoDict->_autocreator = nil;
690 } else {
691 GPBInt32Int32Dictionary *gpbDict = dictionary;
692 gpbDict->_autocreator = nil;
693 }
694 GPBBecomeVisibleToAutocreator(self);
695 return;
696 }
697 }
698 }
699 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self);
700}
701
702void GPBClearMessageAutocreator(GPBMessage *self) {
703 if ((self == nil) || !self->autocreator_) {
704 return;
705 }
706
707#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
708 // Either the autocreator must have its "has" flag set to YES, or it must be
709 // NO and not equal to ourselves.
710 BOOL autocreatorHas =
711 (self->autocreatorField_
712 ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
713 : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
714 GPBMessage *autocreatorFieldValue =
715 (self->autocreatorField_
716 ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_,
717 self->autocreatorField_)
718 : [self->autocreator_->autocreatedExtensionMap_
719 objectForKey:self->autocreatorExtension_]);
720 NSCAssert(autocreatorHas || autocreatorFieldValue != self,
721 @"Cannot clear autocreator because it still refers to self, self: %@.",
722 self);
723
724#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
725
726 self->autocreator_ = nil;
727 [self->autocreatorField_ release];
728 self->autocreatorField_ = nil;
729 [self->autocreatorExtension_ release];
730 self->autocreatorExtension_ = nil;
731}
732
733static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
734 if (!self->unknownFields_) {
735 self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
736 GPBBecomeVisibleToAutocreator(self);
737 }
738 return self->unknownFields_;
739}
740
741@implementation GPBMessage
742
743+ (void)initialize {
744 Class pbMessageClass = [GPBMessage class];
745 if ([self class] == pbMessageClass) {
746 // This is here to start up the "base" class descriptor.
747 [self descriptor];
748 // Message shares extension method resolving with GPBRootObject so insure
749 // it is started up at the same time.
750 (void)[GPBRootObject class];
751 } else if ([self superclass] == pbMessageClass) {
752 // This is here to start up all the "message" subclasses. Just needs to be
753 // done for the messages, not any of the subclasses.
754 // This must be done in initialize to enforce thread safety of start up of
755 // the protocol buffer library.
756 // Note: The generated code for -descriptor calls
757 // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject
758 // subclass for the file. That call chain is what ensures that *Root class
759 // is started up to support extension resolution off the message class
760 // (+resolveClassMethod: below) in a thread safe manner.
761 [self descriptor];
762 }
763}
764
765+ (instancetype)allocWithZone:(NSZone *)zone {
766 // Override alloc to allocate our classes with the additional storage
767 // required for the instance variables.
768 GPBDescriptor *descriptor = [self descriptor];
769 return NSAllocateObject(self, descriptor->storageSize_, zone);
770}
771
772+ (instancetype)alloc {
773 return [self allocWithZone:nil];
774}
775
776+ (GPBDescriptor *)descriptor {
777 // This is thread safe because it is called from +initialize.
778 static GPBDescriptor *descriptor = NULL;
779 static GPBFileDescriptor *fileDescriptor = NULL;
780 if (!descriptor) {
781 // Use a dummy file that marks it as proto2 syntax so when used generically
782 // it supports unknowns/etc.
783 fileDescriptor =
784 [[GPBFileDescriptor alloc] initWithPackage:@"internal"
785 syntax:GPBFileSyntaxProto2];
786
787 descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class]
788 rootClass:Nil
789 file:fileDescriptor
790 fields:NULL
791 fieldCount:0
792 oneofs:NULL
793 oneofCount:0
794 enums:NULL
795 enumCount:0
796 ranges:NULL
797 rangeCount:0
798 storageSize:0
799 wireFormat:NO];
800 }
801 return descriptor;
802}
803
804+ (instancetype)message {
805 return [[[self alloc] init] autorelease];
806}
807
808- (instancetype)init {
809 if ((self = [super init])) {
810 messageStorage_ = (GPBMessage_StoragePtr)(
811 ((uint8_t *)self) + class_getInstanceSize([self class]));
812
813 readOnlySemaphore_ = dispatch_semaphore_create(1);
814 }
815
816 return self;
817}
818
819- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr {
820 return [self initWithData:data extensionRegistry:nil error:errorPtr];
821}
822
823- (instancetype)initWithData:(NSData *)data
824 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
825 error:(NSError **)errorPtr {
826 if ((self = [self init])) {
827 @try {
828 [self mergeFromData:data extensionRegistry:extensionRegistry];
829 if (errorPtr) {
830 *errorPtr = nil;
831 }
832 }
833 @catch (NSException *exception) {
834 [self release];
835 self = nil;
836 if (errorPtr) {
837 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
838 exception.reason);
839 }
840 }
841#ifdef DEBUG
842 if (self && !self.initialized) {
843 [self release];
844 self = nil;
845 if (errorPtr) {
846 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
847 }
848 }
849#endif
850 }
851 return self;
852}
853
854- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
855 extensionRegistry:
856 (GPBExtensionRegistry *)extensionRegistry
857 error:(NSError **)errorPtr {
858 if ((self = [self init])) {
859 @try {
860 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
861 if (errorPtr) {
862 *errorPtr = nil;
863 }
864 }
865 @catch (NSException *exception) {
866 [self release];
867 self = nil;
868 if (errorPtr) {
869 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
870 exception.reason);
871 }
872 }
873#ifdef DEBUG
874 if (self && !self.initialized) {
875 [self release];
876 self = nil;
877 if (errorPtr) {
878 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
879 }
880 }
881#endif
882 }
883 return self;
884}
885
886- (void)dealloc {
887 [self internalClear:NO];
888 NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
889 dispatch_release(readOnlySemaphore_);
890 [super dealloc];
891}
892
893- (void)copyFieldsInto:(GPBMessage *)message
894 zone:(NSZone *)zone
895 descriptor:(GPBDescriptor *)descriptor {
896 // Copy all the storage...
897 memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
898
899 GPBFileSyntax syntax = descriptor.file.syntax;
900
901 // Loop over the fields doing fixup...
902 for (GPBFieldDescriptor *field in descriptor->fields_) {
903 if (GPBFieldIsMapOrArray(field)) {
904 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
905 if (value) {
906 // We need to copy the array/map, but the catch is for message fields,
907 // we also need to ensure all the messages as those need copying also.
908 id newValue;
909 if (GPBFieldDataTypeIsMessage(field)) {
910 if (field.fieldType == GPBFieldTypeRepeated) {
911 NSArray *existingArray = (NSArray *)value;
912 NSMutableArray *newArray =
913 [[NSMutableArray alloc] initWithCapacity:existingArray.count];
914 newValue = newArray;
915 for (GPBMessage *msg in existingArray) {
916 GPBMessage *copiedMsg = [msg copyWithZone:zone];
917 [newArray addObject:copiedMsg];
918 [copiedMsg release];
919 }
920 } else {
921 if (field.mapKeyDataType == GPBDataTypeString) {
922 // Map is an NSDictionary.
923 NSDictionary *existingDict = value;
924 NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
925 initWithCapacity:existingDict.count];
926 newValue = newDict;
927 [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key,
928 GPBMessage *msg,
929 BOOL *stop) {
930#pragma unused(stop)
931 GPBMessage *copiedMsg = [msg copyWithZone:zone];
932 [newDict setObject:copiedMsg forKey:key];
933 [copiedMsg release];
934 }];
935 } else {
936 // Is one of the GPB*ObjectDictionary classes. Type doesn't
937 // matter, just need one to invoke the selector.
938 GPBInt32ObjectDictionary *existingDict = value;
939 newValue = [existingDict deepCopyWithZone:zone];
940 }
941 }
942 } else {
943 // Not messages (but is a map/array)...
944 if (field.fieldType == GPBFieldTypeRepeated) {
945 if (GPBFieldDataTypeIsObject(field)) {
946 // NSArray
947 newValue = [value mutableCopyWithZone:zone];
948 } else {
949 // GPB*Array
950 newValue = [value copyWithZone:zone];
951 }
952 } else {
953 if (field.mapKeyDataType == GPBDataTypeString) {
954 // NSDictionary
955 newValue = [value mutableCopyWithZone:zone];
956 } else {
957 // Is one of the GPB*Dictionary classes. Type doesn't matter,
958 // just need one to invoke the selector.
959 GPBInt32Int32Dictionary *existingDict = value;
960 newValue = [existingDict copyWithZone:zone];
961 }
962 }
963 }
964 // We retain here because the memcpy picked up the pointer value and
965 // the next call to SetRetainedObject... will release the current value.
966 [value retain];
967 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
968 syntax);
969 }
970 } else if (GPBFieldDataTypeIsMessage(field)) {
971 // For object types, if we have a value, copy it. If we don't,
972 // zero it to remove the pointer to something that was autocreated
973 // (and the ptr just got memcpyed).
974 if (GPBGetHasIvarField(self, field)) {
975 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
976 GPBMessage *newValue = [value copyWithZone:zone];
977 // We retain here because the memcpy picked up the pointer value and
978 // the next call to SetRetainedObject... will release the current value.
979 [value retain];
980 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
981 syntax);
982 } else {
983 uint8_t *storage = (uint8_t *)message->messageStorage_;
984 id *typePtr = (id *)&storage[field->description_->offset];
985 *typePtr = NULL;
986 }
987 } else if (GPBFieldDataTypeIsObject(field) &&
988 GPBGetHasIvarField(self, field)) {
989 // A set string/data value (message picked off above), copy it.
990 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
991 id newValue = [value copyWithZone:zone];
992 // We retain here because the memcpy picked up the pointer value and
993 // the next call to SetRetainedObject... will release the current value.
994 [value retain];
995 GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
996 syntax);
997 } else {
998 // memcpy took care of the rest of the primitive fields if they were set.
999 }
1000 } // for (field in descriptor->fields_)
1001}
1002
1003- (id)copyWithZone:(NSZone *)zone {
1004 GPBDescriptor *descriptor = [self descriptor];
1005 GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
1006
1007 [self copyFieldsInto:result zone:zone descriptor:descriptor];
1008 // Make immutable copies of the extra bits.
1009 result->unknownFields_ = [unknownFields_ copyWithZone:zone];
1010 result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
1011 return result;
1012}
1013
1014- (void)clear {
1015 [self internalClear:YES];
1016}
1017
1018- (void)internalClear:(BOOL)zeroStorage {
1019 GPBDescriptor *descriptor = [self descriptor];
1020 for (GPBFieldDescriptor *field in descriptor->fields_) {
1021 if (GPBFieldIsMapOrArray(field)) {
1022 id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1023 if (arrayOrMap) {
1024 if (field.fieldType == GPBFieldTypeRepeated) {
1025 if (GPBFieldDataTypeIsObject(field)) {
1026 GPBAutocreatedArray *autoArray = arrayOrMap;
1027 if (autoArray->_autocreator == self) {
1028 autoArray->_autocreator = nil;
1029 }
1030 } else {
1031 // Type doesn't matter, it is a GPB*Array.
1032 GPBInt32Array *gpbArray = arrayOrMap;
1033 if (gpbArray->_autocreator == self) {
1034 gpbArray->_autocreator = nil;
1035 }
1036 }
1037 } else {
1038 if ((field.mapKeyDataType == GPBDataTypeString) &&
1039 GPBFieldDataTypeIsObject(field)) {
1040 GPBAutocreatedDictionary *autoDict = arrayOrMap;
1041 if (autoDict->_autocreator == self) {
1042 autoDict->_autocreator = nil;
1043 }
1044 } else {
1045 // Type doesn't matter, it is a GPB*Dictionary.
1046 GPBInt32Int32Dictionary *gpbDict = arrayOrMap;
1047 if (gpbDict->_autocreator == self) {
1048 gpbDict->_autocreator = nil;
1049 }
1050 }
1051 }
1052 [arrayOrMap release];
1053 }
1054 } else if (GPBFieldDataTypeIsMessage(field)) {
1055 GPBClearAutocreatedMessageIvarWithField(self, field);
1056 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1057 [value release];
1058 } else if (GPBFieldDataTypeIsObject(field) &&
1059 GPBGetHasIvarField(self, field)) {
1060 id value = GPBGetObjectIvarWithField(self, field);
1061 [value release];
1062 }
1063 }
1064
1065 // GPBClearMessageAutocreator() expects that its caller has already been
1066 // removed from autocreatedExtensionMap_ so we set to nil first.
1067 NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues];
1068 [autocreatedExtensionMap_ release];
1069 autocreatedExtensionMap_ = nil;
1070
1071 // Since we're clearing all of our extensions, make sure that we clear the
1072 // autocreator on any that we've created so they no longer refer to us.
1073 for (GPBMessage *value in autocreatedValues) {
1074 NSCAssert(GPBWasMessageAutocreatedBy(value, self),
1075 @"Autocreated extension does not refer back to self.");
1076 GPBClearMessageAutocreator(value);
1077 }
1078
1079 [extensionMap_ release];
1080 extensionMap_ = nil;
1081 [unknownFields_ release];
1082 unknownFields_ = nil;
1083
1084 // Note that clearing does not affect autocreator_. If we are being cleared
1085 // because of a dealloc, then autocreator_ should be nil anyway. If we are
1086 // being cleared because someone explicitly clears us, we don't want to
1087 // sever our relationship with our autocreator.
1088
1089 if (zeroStorage) {
1090 memset(messageStorage_, 0, descriptor->storageSize_);
1091 }
1092}
1093
1094- (BOOL)isInitialized {
1095 GPBDescriptor *descriptor = [self descriptor];
1096 for (GPBFieldDescriptor *field in descriptor->fields_) {
1097 if (field.isRequired) {
1098 if (!GPBGetHasIvarField(self, field)) {
1099 return NO;
1100 }
1101 }
1102 if (GPBFieldDataTypeIsMessage(field)) {
1103 GPBFieldType fieldType = field.fieldType;
1104 if (fieldType == GPBFieldTypeSingle) {
1105 if (field.isRequired) {
1106 GPBMessage *message = GPBGetMessageMessageField(self, field);
1107 if (!message.initialized) {
1108 return NO;
1109 }
1110 } else {
1111 NSAssert(field.isOptional,
1112 @"%@: Single message field %@ not required or optional?",
1113 [self class], field.name);
1114 if (GPBGetHasIvarField(self, field)) {
1115 GPBMessage *message = GPBGetMessageMessageField(self, field);
1116 if (!message.initialized) {
1117 return NO;
1118 }
1119 }
1120 }
1121 } else if (fieldType == GPBFieldTypeRepeated) {
1122 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1123 for (GPBMessage *message in array) {
1124 if (!message.initialized) {
1125 return NO;
1126 }
1127 }
1128 } else { // fieldType == GPBFieldTypeMap
1129 if (field.mapKeyDataType == GPBDataTypeString) {
1130 NSDictionary *map =
1131 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1132 if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
1133 return NO;
1134 }
1135 } else {
1136 // Real type is GPB*ObjectDictionary, exact type doesn't matter.
1137 GPBInt32ObjectDictionary *map =
1138 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1139 if (map && ![map isInitialized]) {
1140 return NO;
1141 }
1142 }
1143 }
1144 }
1145 }
1146
1147 __block BOOL result = YES;
1148 [extensionMap_
1149 enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension,
1150 id obj,
1151 BOOL *stop) {
1152 if (GPBExtensionIsMessage(extension)) {
1153 if (extension.isRepeated) {
1154 for (GPBMessage *msg in obj) {
1155 if (!msg.initialized) {
1156 result = NO;
1157 *stop = YES;
1158 break;
1159 }
1160 }
1161 } else {
1162 GPBMessage *asMsg = obj;
1163 if (!asMsg.initialized) {
1164 result = NO;
1165 *stop = YES;
1166 }
1167 }
1168 }
1169 }];
1170 return result;
1171}
1172
1173- (GPBDescriptor *)descriptor {
1174 return [[self class] descriptor];
1175}
1176
1177- (NSData *)data {
1178#ifdef DEBUG
1179 if (!self.initialized) {
1180 return nil;
1181 }
1182#endif
1183 NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]];
1184 GPBCodedOutputStream *stream =
1185 [[GPBCodedOutputStream alloc] initWithData:data];
1186 @try {
1187 [self writeToCodedOutputStream:stream];
1188 }
1189 @catch (NSException *exception) {
1190 // This really shouldn't happen. The only way writeToCodedOutputStream:
1191 // could throw is if something in the library has a bug and the
1192 // serializedSize was wrong.
1193#ifdef DEBUG
1194 NSLog(@"%@: Internal exception while building message data: %@",
1195 [self class], exception);
1196#endif
1197 data = nil;
1198 }
1199 [stream release];
1200 return data;
1201}
1202
1203- (NSData *)delimitedData {
1204 size_t serializedSize = [self serializedSize];
1205 size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
1206 NSMutableData *data =
1207 [NSMutableData dataWithLength:(serializedSize + varintSize)];
1208 GPBCodedOutputStream *stream =
1209 [[GPBCodedOutputStream alloc] initWithData:data];
1210 @try {
1211 [self writeDelimitedToCodedOutputStream:stream];
1212 }
1213 @catch (NSException *exception) {
1214 // This really shouldn't happen. The only way writeToCodedOutputStream:
1215 // could throw is if something in the library has a bug and the
1216 // serializedSize was wrong.
1217#ifdef DEBUG
1218 NSLog(@"%@: Internal exception while building message delimitedData: %@",
1219 [self class], exception);
1220#endif
1221 // If it happens, truncate.
1222 data.length = 0;
1223 }
1224 [stream release];
1225 return data;
1226}
1227
1228- (void)writeToOutputStream:(NSOutputStream *)output {
1229 GPBCodedOutputStream *stream =
1230 [[GPBCodedOutputStream alloc] initWithOutputStream:output];
1231 [self writeToCodedOutputStream:stream];
1232 [stream release];
1233}
1234
1235- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
1236 GPBDescriptor *descriptor = [self descriptor];
1237 NSArray *fieldsArray = descriptor->fields_;
1238 NSUInteger fieldCount = fieldsArray.count;
1239 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
1240 NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
1241 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
1242 if (i == fieldCount) {
1243 [self writeExtensionsToCodedOutputStream:output
1244 range:extensionRanges[j++]];
1245 } else if (j == extensionRangesCount ||
1246 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
1247 [self writeField:fieldsArray[i++] toCodedOutputStream:output];
1248 } else {
1249 [self writeExtensionsToCodedOutputStream:output
1250 range:extensionRanges[j++]];
1251 }
1252 }
1253 if (descriptor.isWireFormat) {
1254 [unknownFields_ writeAsMessageSetTo:output];
1255 } else {
1256 [unknownFields_ writeToCodedOutputStream:output];
1257 }
1258}
1259
1260- (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
1261 GPBCodedOutputStream *codedOutput =
1262 [[GPBCodedOutputStream alloc] initWithOutputStream:output];
1263 [self writeDelimitedToCodedOutputStream:codedOutput];
1264 [codedOutput release];
1265}
1266
1267- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output {
1268 [output writeRawVarintSizeTAs32:[self serializedSize]];
1269 [self writeToCodedOutputStream:output];
1270}
1271
1272- (void)writeField:(GPBFieldDescriptor *)field
1273 toCodedOutputStream:(GPBCodedOutputStream *)output {
1274 GPBFieldType fieldType = field.fieldType;
1275 if (fieldType == GPBFieldTypeSingle) {
1276 BOOL has = GPBGetHasIvarField(self, field);
1277 if (!has) {
1278 return;
1279 }
1280 }
1281 uint32_t fieldNumber = GPBFieldNumber(field);
1282
1283//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
1284//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
1285//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
1286//% case GPBDataType##TYPE:
1287//% if (fieldType == GPBFieldTypeRepeated) {
1288//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1289//% GPB##ARRAY_TYPE##Array *array =
1290//% GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1291//% [output write##TYPE##Array:fieldNumber values:array tag:tag];
1292//% } else if (fieldType == GPBFieldTypeSingle) {
1293//% [output write##TYPE:fieldNumber
1294//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)];
1295//% } else { // fieldType == GPBFieldTypeMap
1296//% // Exact type here doesn't matter.
1297//% GPBInt32##ARRAY_TYPE##Dictionary *dict =
1298//% GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1299//% [dict writeToCodedOutputStream:output asField:field];
1300//% }
1301//% break;
1302//%
1303//%PDDM-DEFINE FIELD_CASE2(TYPE)
1304//% case GPBDataType##TYPE:
1305//% if (fieldType == GPBFieldTypeRepeated) {
1306//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1307//% [output write##TYPE##Array:fieldNumber values:array];
1308//% } else if (fieldType == GPBFieldTypeSingle) {
1309//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1310//% // again.
1311//% [output write##TYPE:fieldNumber
1312//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1313//% } else { // fieldType == GPBFieldTypeMap
1314//% // Exact type here doesn't matter.
1315//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1316//% GPBDataType mapKeyDataType = field.mapKeyDataType;
1317//% if (mapKeyDataType == GPBDataTypeString) {
1318//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1319//% } else {
1320//% [dict writeToCodedOutputStream:output asField:field];
1321//% }
1322//% }
1323//% break;
1324//%
1325
1326 switch (GPBGetFieldDataType(field)) {
1327
1328//%PDDM-EXPAND FIELD_CASE(Bool, Bool)
1329// This block of code is generated, do not edit it directly.
1330
1331 case GPBDataTypeBool:
1332 if (fieldType == GPBFieldTypeRepeated) {
1333 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1334 GPBBoolArray *array =
1335 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1336 [output writeBoolArray:fieldNumber values:array tag:tag];
1337 } else if (fieldType == GPBFieldTypeSingle) {
1338 [output writeBool:fieldNumber
1339 value:GPBGetMessageBoolField(self, field)];
1340 } else { // fieldType == GPBFieldTypeMap
1341 // Exact type here doesn't matter.
1342 GPBInt32BoolDictionary *dict =
1343 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1344 [dict writeToCodedOutputStream:output asField:field];
1345 }
1346 break;
1347
1348//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
1349// This block of code is generated, do not edit it directly.
1350
1351 case GPBDataTypeFixed32:
1352 if (fieldType == GPBFieldTypeRepeated) {
1353 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1354 GPBUInt32Array *array =
1355 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1356 [output writeFixed32Array:fieldNumber values:array tag:tag];
1357 } else if (fieldType == GPBFieldTypeSingle) {
1358 [output writeFixed32:fieldNumber
1359 value:GPBGetMessageUInt32Field(self, field)];
1360 } else { // fieldType == GPBFieldTypeMap
1361 // Exact type here doesn't matter.
1362 GPBInt32UInt32Dictionary *dict =
1363 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1364 [dict writeToCodedOutputStream:output asField:field];
1365 }
1366 break;
1367
1368//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
1369// This block of code is generated, do not edit it directly.
1370
1371 case GPBDataTypeSFixed32:
1372 if (fieldType == GPBFieldTypeRepeated) {
1373 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1374 GPBInt32Array *array =
1375 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1376 [output writeSFixed32Array:fieldNumber values:array tag:tag];
1377 } else if (fieldType == GPBFieldTypeSingle) {
1378 [output writeSFixed32:fieldNumber
1379 value:GPBGetMessageInt32Field(self, field)];
1380 } else { // fieldType == GPBFieldTypeMap
1381 // Exact type here doesn't matter.
1382 GPBInt32Int32Dictionary *dict =
1383 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1384 [dict writeToCodedOutputStream:output asField:field];
1385 }
1386 break;
1387
1388//%PDDM-EXPAND FIELD_CASE(Float, Float)
1389// This block of code is generated, do not edit it directly.
1390
1391 case GPBDataTypeFloat:
1392 if (fieldType == GPBFieldTypeRepeated) {
1393 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1394 GPBFloatArray *array =
1395 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1396 [output writeFloatArray:fieldNumber values:array tag:tag];
1397 } else if (fieldType == GPBFieldTypeSingle) {
1398 [output writeFloat:fieldNumber
1399 value:GPBGetMessageFloatField(self, field)];
1400 } else { // fieldType == GPBFieldTypeMap
1401 // Exact type here doesn't matter.
1402 GPBInt32FloatDictionary *dict =
1403 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1404 [dict writeToCodedOutputStream:output asField:field];
1405 }
1406 break;
1407
1408//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
1409// This block of code is generated, do not edit it directly.
1410
1411 case GPBDataTypeFixed64:
1412 if (fieldType == GPBFieldTypeRepeated) {
1413 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1414 GPBUInt64Array *array =
1415 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1416 [output writeFixed64Array:fieldNumber values:array tag:tag];
1417 } else if (fieldType == GPBFieldTypeSingle) {
1418 [output writeFixed64:fieldNumber
1419 value:GPBGetMessageUInt64Field(self, field)];
1420 } else { // fieldType == GPBFieldTypeMap
1421 // Exact type here doesn't matter.
1422 GPBInt32UInt64Dictionary *dict =
1423 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1424 [dict writeToCodedOutputStream:output asField:field];
1425 }
1426 break;
1427
1428//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
1429// This block of code is generated, do not edit it directly.
1430
1431 case GPBDataTypeSFixed64:
1432 if (fieldType == GPBFieldTypeRepeated) {
1433 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1434 GPBInt64Array *array =
1435 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1436 [output writeSFixed64Array:fieldNumber values:array tag:tag];
1437 } else if (fieldType == GPBFieldTypeSingle) {
1438 [output writeSFixed64:fieldNumber
1439 value:GPBGetMessageInt64Field(self, field)];
1440 } else { // fieldType == GPBFieldTypeMap
1441 // Exact type here doesn't matter.
1442 GPBInt32Int64Dictionary *dict =
1443 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1444 [dict writeToCodedOutputStream:output asField:field];
1445 }
1446 break;
1447
1448//%PDDM-EXPAND FIELD_CASE(Double, Double)
1449// This block of code is generated, do not edit it directly.
1450
1451 case GPBDataTypeDouble:
1452 if (fieldType == GPBFieldTypeRepeated) {
1453 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1454 GPBDoubleArray *array =
1455 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1456 [output writeDoubleArray:fieldNumber values:array tag:tag];
1457 } else if (fieldType == GPBFieldTypeSingle) {
1458 [output writeDouble:fieldNumber
1459 value:GPBGetMessageDoubleField(self, field)];
1460 } else { // fieldType == GPBFieldTypeMap
1461 // Exact type here doesn't matter.
1462 GPBInt32DoubleDictionary *dict =
1463 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1464 [dict writeToCodedOutputStream:output asField:field];
1465 }
1466 break;
1467
1468//%PDDM-EXPAND FIELD_CASE(Int32, Int32)
1469// This block of code is generated, do not edit it directly.
1470
1471 case GPBDataTypeInt32:
1472 if (fieldType == GPBFieldTypeRepeated) {
1473 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1474 GPBInt32Array *array =
1475 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1476 [output writeInt32Array:fieldNumber values:array tag:tag];
1477 } else if (fieldType == GPBFieldTypeSingle) {
1478 [output writeInt32:fieldNumber
1479 value:GPBGetMessageInt32Field(self, field)];
1480 } else { // fieldType == GPBFieldTypeMap
1481 // Exact type here doesn't matter.
1482 GPBInt32Int32Dictionary *dict =
1483 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1484 [dict writeToCodedOutputStream:output asField:field];
1485 }
1486 break;
1487
1488//%PDDM-EXPAND FIELD_CASE(Int64, Int64)
1489// This block of code is generated, do not edit it directly.
1490
1491 case GPBDataTypeInt64:
1492 if (fieldType == GPBFieldTypeRepeated) {
1493 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1494 GPBInt64Array *array =
1495 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1496 [output writeInt64Array:fieldNumber values:array tag:tag];
1497 } else if (fieldType == GPBFieldTypeSingle) {
1498 [output writeInt64:fieldNumber
1499 value:GPBGetMessageInt64Field(self, field)];
1500 } else { // fieldType == GPBFieldTypeMap
1501 // Exact type here doesn't matter.
1502 GPBInt32Int64Dictionary *dict =
1503 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1504 [dict writeToCodedOutputStream:output asField:field];
1505 }
1506 break;
1507
1508//%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
1509// This block of code is generated, do not edit it directly.
1510
1511 case GPBDataTypeSInt32:
1512 if (fieldType == GPBFieldTypeRepeated) {
1513 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1514 GPBInt32Array *array =
1515 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1516 [output writeSInt32Array:fieldNumber values:array tag:tag];
1517 } else if (fieldType == GPBFieldTypeSingle) {
1518 [output writeSInt32:fieldNumber
1519 value:GPBGetMessageInt32Field(self, field)];
1520 } else { // fieldType == GPBFieldTypeMap
1521 // Exact type here doesn't matter.
1522 GPBInt32Int32Dictionary *dict =
1523 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1524 [dict writeToCodedOutputStream:output asField:field];
1525 }
1526 break;
1527
1528//%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
1529// This block of code is generated, do not edit it directly.
1530
1531 case GPBDataTypeSInt64:
1532 if (fieldType == GPBFieldTypeRepeated) {
1533 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1534 GPBInt64Array *array =
1535 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1536 [output writeSInt64Array:fieldNumber values:array tag:tag];
1537 } else if (fieldType == GPBFieldTypeSingle) {
1538 [output writeSInt64:fieldNumber
1539 value:GPBGetMessageInt64Field(self, field)];
1540 } else { // fieldType == GPBFieldTypeMap
1541 // Exact type here doesn't matter.
1542 GPBInt32Int64Dictionary *dict =
1543 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1544 [dict writeToCodedOutputStream:output asField:field];
1545 }
1546 break;
1547
1548//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
1549// This block of code is generated, do not edit it directly.
1550
1551 case GPBDataTypeUInt32:
1552 if (fieldType == GPBFieldTypeRepeated) {
1553 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1554 GPBUInt32Array *array =
1555 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1556 [output writeUInt32Array:fieldNumber values:array tag:tag];
1557 } else if (fieldType == GPBFieldTypeSingle) {
1558 [output writeUInt32:fieldNumber
1559 value:GPBGetMessageUInt32Field(self, field)];
1560 } else { // fieldType == GPBFieldTypeMap
1561 // Exact type here doesn't matter.
1562 GPBInt32UInt32Dictionary *dict =
1563 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1564 [dict writeToCodedOutputStream:output asField:field];
1565 }
1566 break;
1567
1568//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
1569// This block of code is generated, do not edit it directly.
1570
1571 case GPBDataTypeUInt64:
1572 if (fieldType == GPBFieldTypeRepeated) {
1573 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1574 GPBUInt64Array *array =
1575 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1576 [output writeUInt64Array:fieldNumber values:array tag:tag];
1577 } else if (fieldType == GPBFieldTypeSingle) {
1578 [output writeUInt64:fieldNumber
1579 value:GPBGetMessageUInt64Field(self, field)];
1580 } else { // fieldType == GPBFieldTypeMap
1581 // Exact type here doesn't matter.
1582 GPBInt32UInt64Dictionary *dict =
1583 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1584 [dict writeToCodedOutputStream:output asField:field];
1585 }
1586 break;
1587
1588//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
1589// This block of code is generated, do not edit it directly.
1590
1591 case GPBDataTypeEnum:
1592 if (fieldType == GPBFieldTypeRepeated) {
1593 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
1594 GPBEnumArray *array =
1595 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1596 [output writeEnumArray:fieldNumber values:array tag:tag];
1597 } else if (fieldType == GPBFieldTypeSingle) {
1598 [output writeEnum:fieldNumber
1599 value:GPBGetMessageInt32Field(self, field)];
1600 } else { // fieldType == GPBFieldTypeMap
1601 // Exact type here doesn't matter.
1602 GPBInt32EnumDictionary *dict =
1603 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1604 [dict writeToCodedOutputStream:output asField:field];
1605 }
1606 break;
1607
1608//%PDDM-EXPAND FIELD_CASE2(Bytes)
1609// This block of code is generated, do not edit it directly.
1610
1611 case GPBDataTypeBytes:
1612 if (fieldType == GPBFieldTypeRepeated) {
1613 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1614 [output writeBytesArray:fieldNumber values:array];
1615 } else if (fieldType == GPBFieldTypeSingle) {
1616 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1617 // again.
1618 [output writeBytes:fieldNumber
1619 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1620 } else { // fieldType == GPBFieldTypeMap
1621 // Exact type here doesn't matter.
1622 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1623 GPBDataType mapKeyDataType = field.mapKeyDataType;
1624 if (mapKeyDataType == GPBDataTypeString) {
1625 GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1626 } else {
1627 [dict writeToCodedOutputStream:output asField:field];
1628 }
1629 }
1630 break;
1631
1632//%PDDM-EXPAND FIELD_CASE2(String)
1633// This block of code is generated, do not edit it directly.
1634
1635 case GPBDataTypeString:
1636 if (fieldType == GPBFieldTypeRepeated) {
1637 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1638 [output writeStringArray:fieldNumber values:array];
1639 } else if (fieldType == GPBFieldTypeSingle) {
1640 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1641 // again.
1642 [output writeString:fieldNumber
1643 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1644 } else { // fieldType == GPBFieldTypeMap
1645 // Exact type here doesn't matter.
1646 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1647 GPBDataType mapKeyDataType = field.mapKeyDataType;
1648 if (mapKeyDataType == GPBDataTypeString) {
1649 GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1650 } else {
1651 [dict writeToCodedOutputStream:output asField:field];
1652 }
1653 }
1654 break;
1655
1656//%PDDM-EXPAND FIELD_CASE2(Message)
1657// This block of code is generated, do not edit it directly.
1658
1659 case GPBDataTypeMessage:
1660 if (fieldType == GPBFieldTypeRepeated) {
1661 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1662 [output writeMessageArray:fieldNumber values:array];
1663 } else if (fieldType == GPBFieldTypeSingle) {
1664 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1665 // again.
1666 [output writeMessage:fieldNumber
1667 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1668 } else { // fieldType == GPBFieldTypeMap
1669 // Exact type here doesn't matter.
1670 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1671 GPBDataType mapKeyDataType = field.mapKeyDataType;
1672 if (mapKeyDataType == GPBDataTypeString) {
1673 GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1674 } else {
1675 [dict writeToCodedOutputStream:output asField:field];
1676 }
1677 }
1678 break;
1679
1680//%PDDM-EXPAND FIELD_CASE2(Group)
1681// This block of code is generated, do not edit it directly.
1682
1683 case GPBDataTypeGroup:
1684 if (fieldType == GPBFieldTypeRepeated) {
1685 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1686 [output writeGroupArray:fieldNumber values:array];
1687 } else if (fieldType == GPBFieldTypeSingle) {
1688 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
1689 // again.
1690 [output writeGroup:fieldNumber
1691 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
1692 } else { // fieldType == GPBFieldTypeMap
1693 // Exact type here doesn't matter.
1694 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
1695 GPBDataType mapKeyDataType = field.mapKeyDataType;
1696 if (mapKeyDataType == GPBDataTypeString) {
1697 GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
1698 } else {
1699 [dict writeToCodedOutputStream:output asField:field];
1700 }
1701 }
1702 break;
1703
1704//%PDDM-EXPAND-END (18 expansions)
1705 }
1706}
1707
1708#pragma mark - Extensions
1709
1710- (id)getExtension:(GPBExtensionDescriptor *)extension {
1711 CheckExtension(self, extension);
1712 id value = [extensionMap_ objectForKey:extension];
1713 if (value != nil) {
1714 return value;
1715 }
1716
1717 // No default for repeated.
1718 if (extension.isRepeated) {
1719 return nil;
1720 }
1721 // Non messages get their default.
1722 if (!GPBExtensionIsMessage(extension)) {
1723 return extension.defaultValue;
1724 }
1725
1726 // Check for an autocreated value.
1727 dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER);
1728 value = [autocreatedExtensionMap_ objectForKey:extension];
1729 if (!value) {
1730 // Auto create the message extensions to match normal fields.
1731 value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self,
1732 extension);
1733
1734 if (autocreatedExtensionMap_ == nil) {
1735 autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init];
1736 }
1737
1738 // We can't simply call setExtension here because that would clear the new
1739 // value's autocreator.
1740 [autocreatedExtensionMap_ setObject:value forKey:extension];
1741 [value release];
1742 }
1743
1744 dispatch_semaphore_signal(readOnlySemaphore_);
1745 return value;
1746}
1747
1748- (id)getExistingExtension:(GPBExtensionDescriptor *)extension {
1749 // This is an internal method so we don't need to call CheckExtension().
1750 return [extensionMap_ objectForKey:extension];
1751}
1752
1753- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension {
1754#if DEBUG
1755 CheckExtension(self, extension);
1756#endif // DEBUG
1757 return nil != [extensionMap_ objectForKey:extension];
1758}
1759
1760- (NSArray *)extensionsCurrentlySet {
1761 return [extensionMap_ allKeys];
1762}
1763
1764- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output
1765 range:(GPBExtensionRange)range {
1766 NSArray *sortedExtensions = [[extensionMap_ allKeys]
1767 sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
1768 uint32_t start = range.start;
1769 uint32_t end = range.end;
1770 for (GPBExtensionDescriptor *extension in sortedExtensions) {
1771 uint32_t fieldNumber = extension.fieldNumber;
1772 if (fieldNumber >= start && fieldNumber < end) {
1773 id value = [extensionMap_ objectForKey:extension];
1774 GPBWriteExtensionValueToOutputStream(extension, value, output);
1775 }
1776 }
1777}
1778
1779- (NSArray *)sortedExtensionsInUse {
1780 return [[extensionMap_ allKeys]
1781 sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
1782}
1783
1784- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value {
1785 if (!value) {
1786 [self clearExtension:extension];
1787 return;
1788 }
1789
1790 CheckExtension(self, extension);
1791
1792 if (extension.repeated) {
1793 [NSException raise:NSInvalidArgumentException
1794 format:@"Must call addExtension() for repeated types."];
1795 }
1796
1797 if (extensionMap_ == nil) {
1798 extensionMap_ = [[NSMutableDictionary alloc] init];
1799 }
1800
1801 // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION.
1802 // Without it, the compiler complains we're passing an id nullable when
1803 // setObject:forKey: requires a id nonnull for the value. The check for
1804 // !value at the start of the method ensures it isn't nil, but the check
1805 // isn't smart enough to realize that.
1806 [extensionMap_ setObject:(id)value forKey:extension];
1807
1808 GPBExtensionDescriptor *descriptor = extension;
1809
1810 if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
1811 GPBMessage *autocreatedValue =
1812 [[autocreatedExtensionMap_ objectForKey:extension] retain];
1813 // Must remove from the map before calling GPBClearMessageAutocreator() so
1814 // that GPBClearMessageAutocreator() knows its safe to clear.
1815 [autocreatedExtensionMap_ removeObjectForKey:extension];
1816 GPBClearMessageAutocreator(autocreatedValue);
1817 [autocreatedValue release];
1818 }
1819
1820 GPBBecomeVisibleToAutocreator(self);
1821}
1822
1823- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value {
1824 CheckExtension(self, extension);
1825
1826 if (!extension.repeated) {
1827 [NSException raise:NSInvalidArgumentException
1828 format:@"Must call setExtension() for singular types."];
1829 }
1830
1831 if (extensionMap_ == nil) {
1832 extensionMap_ = [[NSMutableDictionary alloc] init];
1833 }
1834 NSMutableArray *list = [extensionMap_ objectForKey:extension];
1835 if (list == nil) {
1836 list = [NSMutableArray array];
1837 [extensionMap_ setObject:list forKey:extension];
1838 }
1839
1840 [list addObject:value];
1841 GPBBecomeVisibleToAutocreator(self);
1842}
1843
1844- (void)setExtension:(GPBExtensionDescriptor *)extension
1845 index:(NSUInteger)idx
1846 value:(id)value {
1847 CheckExtension(self, extension);
1848
1849 if (!extension.repeated) {
1850 [NSException raise:NSInvalidArgumentException
1851 format:@"Must call setExtension() for singular types."];
1852 }
1853
1854 if (extensionMap_ == nil) {
1855 extensionMap_ = [[NSMutableDictionary alloc] init];
1856 }
1857
1858 NSMutableArray *list = [extensionMap_ objectForKey:extension];
1859
1860 [list replaceObjectAtIndex:idx withObject:value];
1861 GPBBecomeVisibleToAutocreator(self);
1862}
1863
1864- (void)clearExtension:(GPBExtensionDescriptor *)extension {
1865 CheckExtension(self, extension);
1866
1867 // Only become visible if there was actually a value to clear.
1868 if ([extensionMap_ objectForKey:extension]) {
1869 [extensionMap_ removeObjectForKey:extension];
1870 GPBBecomeVisibleToAutocreator(self);
1871 }
1872}
1873
1874#pragma mark - mergeFrom
1875
1876- (void)mergeFromData:(NSData *)data
1877 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
1878 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
1879 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
1880 [input checkLastTagWas:0];
1881 [input release];
1882}
1883
1884#pragma mark - mergeDelimitedFrom
1885
1886- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
1887 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
1888 GPBCodedInputStreamState *state = &input->state_;
1889 if (GPBCodedInputStreamIsAtEnd(state)) {
1890 return;
1891 }
1892 NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state);
1893 if (data == nil) {
1894 return;
1895 }
1896 [self mergeFromData:data extensionRegistry:extensionRegistry];
1897 [data release];
1898}
1899
1900#pragma mark - Parse From Data Support
1901
1902+ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr {
1903 return [self parseFromData:data extensionRegistry:nil error:errorPtr];
1904}
1905
1906+ (instancetype)parseFromData:(NSData *)data
1907 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
1908 error:(NSError **)errorPtr {
1909 return [[[self alloc] initWithData:data
1910 extensionRegistry:extensionRegistry
1911 error:errorPtr] autorelease];
1912}
1913
1914+ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
1915 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
1916 error:(NSError **)errorPtr {
1917 return
1918 [[[self alloc] initWithCodedInputStream:input
1919 extensionRegistry:extensionRegistry
1920 error:errorPtr] autorelease];
1921}
1922
1923#pragma mark - Parse Delimited From Data Support
1924
1925+ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
1926 extensionRegistry:
1927 (GPBExtensionRegistry *)extensionRegistry
1928 error:(NSError **)errorPtr {
1929 GPBMessage *message = [[[self alloc] init] autorelease];
1930 @try {
1931 [message mergeDelimitedFromCodedInputStream:input
1932 extensionRegistry:extensionRegistry];
1933 if (errorPtr) {
1934 *errorPtr = nil;
1935 }
1936 }
1937 @catch (NSException *exception) {
1938 [message release];
1939 message = nil;
1940 if (errorPtr) {
1941 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData,
1942 exception.reason);
1943 }
1944 }
1945#ifdef DEBUG
1946 if (message && !message.initialized) {
1947 [message release];
1948 message = nil;
1949 if (errorPtr) {
1950 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil);
1951 }
1952 }
1953#endif
1954 return message;
1955}
1956
1957#pragma mark - Unknown Field Support
1958
1959- (GPBUnknownFieldSet *)unknownFields {
1960 return unknownFields_;
1961}
1962
1963- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
1964 if (unknownFields != unknownFields_) {
1965 [unknownFields_ release];
1966 unknownFields_ = [unknownFields copy];
1967 GPBBecomeVisibleToAutocreator(self);
1968 }
1969}
1970
1971- (void)parseMessageSet:(GPBCodedInputStream *)input
1972 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
1973 uint32_t typeId = 0;
1974 NSData *rawBytes = nil;
1975 GPBExtensionDescriptor *extension = nil;
1976 GPBCodedInputStreamState *state = &input->state_;
1977 while (true) {
1978 uint32_t tag = GPBCodedInputStreamReadTag(state);
1979 if (tag == 0) {
1980 break;
1981 }
1982
1983 if (tag == GPBWireFormatMessageSetTypeIdTag) {
1984 typeId = GPBCodedInputStreamReadUInt32(state);
1985 if (typeId != 0) {
1986 extension = [extensionRegistry extensionForDescriptor:[self descriptor]
1987 fieldNumber:typeId];
1988 }
1989 } else if (tag == GPBWireFormatMessageSetMessageTag) {
1990 rawBytes =
1991 [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease];
1992 } else {
1993 if (![input skipField:tag]) {
1994 break;
1995 }
1996 }
1997 }
1998
1999 [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag];
2000
2001 if (rawBytes != nil && typeId != 0) {
2002 if (extension != nil) {
2003 GPBCodedInputStream *newInput =
2004 [[GPBCodedInputStream alloc] initWithData:rawBytes];
2005 GPBExtensionMergeFromInputStream(extension,
2006 extension.packable,
2007 newInput,
2008 extensionRegistry,
2009 self);
2010 [newInput release];
2011 } else {
2012 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2013 [unknownFields mergeMessageSetMessage:typeId data:rawBytes];
2014 }
2015 }
2016}
2017
2018- (BOOL)parseUnknownField:(GPBCodedInputStream *)input
2019 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
2020 tag:(uint32_t)tag {
2021 GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
2022 int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
2023
2024 GPBDescriptor *descriptor = [self descriptor];
2025 GPBExtensionDescriptor *extension =
2026 [extensionRegistry extensionForDescriptor:descriptor
2027 fieldNumber:fieldNumber];
2028 if (extension == nil) {
2029 if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
2030 [self parseMessageSet:input extensionRegistry:extensionRegistry];
2031 return YES;
2032 }
2033 } else {
2034 if (extension.wireType == wireType) {
2035 GPBExtensionMergeFromInputStream(extension,
2036 extension.packable,
2037 input,
2038 extensionRegistry,
2039 self);
2040 return YES;
2041 }
2042 // Primitive, repeated types can be packed on unpacked on the wire, and are
2043 // parsed either way.
2044 if ([extension isRepeated] &&
2045 !GPBDataTypeIsObject(extension->description_->dataType) &&
2046 (extension.alternateWireType == wireType)) {
2047 GPBExtensionMergeFromInputStream(extension,
2048 !extension.packable,
2049 input,
2050 extensionRegistry,
2051 self);
2052 return YES;
2053 }
2054 }
2055 if ([GPBUnknownFieldSet isFieldTag:tag]) {
2056 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2057 return [unknownFields mergeFieldFrom:tag input:input];
2058 } else {
2059 return NO;
2060 }
2061}
2062
2063- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
2064 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2065 [unknownFields addUnknownMapEntry:fieldNum value:data];
2066}
2067
2068#pragma mark - MergeFromCodedInputStream Support
2069
2070static void MergeSingleFieldFromCodedInputStream(
2071 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
2072 GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
2073 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2074 switch (fieldDataType) {
2075#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \
2076 case GPBDataType##NAME: { \
2077 TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \
2078 GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \
2079 break; \
2080 }
2081#define CASE_SINGLE_OBJECT(NAME) \
2082 case GPBDataType##NAME: { \
2083 id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \
2084 GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \
2085 break; \
2086 }
2087 CASE_SINGLE_POD(Bool, BOOL, Bool)
2088 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
2089 CASE_SINGLE_POD(SFixed32, int32_t, Int32)
2090 CASE_SINGLE_POD(Float, float, Float)
2091 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
2092 CASE_SINGLE_POD(SFixed64, int64_t, Int64)
2093 CASE_SINGLE_POD(Double, double, Double)
2094 CASE_SINGLE_POD(Int32, int32_t, Int32)
2095 CASE_SINGLE_POD(Int64, int64_t, Int64)
2096 CASE_SINGLE_POD(SInt32, int32_t, Int32)
2097 CASE_SINGLE_POD(SInt64, int64_t, Int64)
2098 CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
2099 CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
2100 CASE_SINGLE_OBJECT(Bytes)
2101 CASE_SINGLE_OBJECT(String)
2102#undef CASE_SINGLE_POD
2103#undef CASE_SINGLE_OBJECT
2104
2105 case GPBDataTypeMessage: {
2106 if (GPBGetHasIvarField(self, field)) {
2107 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
2108 // check again.
2109 GPBMessage *message =
2110 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2111 [input readMessage:message extensionRegistry:extensionRegistry];
2112 } else {
2113 GPBMessage *message = [[field.msgClass alloc] init];
2114 [input readMessage:message extensionRegistry:extensionRegistry];
2115 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
2116 }
2117 break;
2118 }
2119
2120 case GPBDataTypeGroup: {
2121 if (GPBGetHasIvarField(self, field)) {
2122 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has
2123 // check again.
2124 GPBMessage *message =
2125 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2126 [input readGroup:GPBFieldNumber(field)
2127 message:message
2128 extensionRegistry:extensionRegistry];
2129 } else {
2130 GPBMessage *message = [[field.msgClass alloc] init];
2131 [input readGroup:GPBFieldNumber(field)
2132 message:message
2133 extensionRegistry:extensionRegistry];
2134 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax);
2135 }
2136 break;
2137 }
2138
2139 case GPBDataTypeEnum: {
2140 int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
2141 if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
2142 [field isValidEnumValue:val]) {
2143 GPBSetInt32IvarWithFieldInternal(self, field, val, syntax);
2144 } else {
2145 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2146 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
2147 }
2148 }
2149 } // switch
2150}
2151
2152static void MergeRepeatedPackedFieldFromCodedInputStream(
2153 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
2154 GPBCodedInputStream *input) {
2155 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2156 GPBCodedInputStreamState *state = &input->state_;
2157 id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
2158 int32_t length = GPBCodedInputStreamReadInt32(state);
2159 size_t limit = GPBCodedInputStreamPushLimit(state, length);
2160 while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
2161 switch (fieldDataType) {
2162#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
2163 case GPBDataType##NAME: { \
2164 TYPE val = GPBCodedInputStreamRead##NAME(state); \
2165 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
2166 break; \
2167 }
2168 CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool)
2169 CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32)
2170 CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32)
2171 CASE_REPEATED_PACKED_POD(Float, float, Float)
2172 CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64)
2173 CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64)
2174 CASE_REPEATED_PACKED_POD(Double, double, Double)
2175 CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32)
2176 CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64)
2177 CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32)
2178 CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64)
2179 CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32)
2180 CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64)
2181#undef CASE_REPEATED_PACKED_POD
2182
2183 case GPBDataTypeBytes:
2184 case GPBDataTypeString:
2185 case GPBDataTypeMessage:
2186 case GPBDataTypeGroup:
2187 NSCAssert(NO, @"Non primitive types can't be packed");
2188 break;
2189
2190 case GPBDataTypeEnum: {
2191 int32_t val = GPBCodedInputStreamReadEnum(state);
2192 if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
2193 [field isValidEnumValue:val]) {
2194 [(GPBEnumArray*)genericArray addRawValue:val];
2195 } else {
2196 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2197 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
2198 }
2199 break;
2200 }
2201 } // switch
2202 } // while(BytesUntilLimit() > 0)
2203 GPBCodedInputStreamPopLimit(state, limit);
2204}
2205
2206static void MergeRepeatedNotPackedFieldFromCodedInputStream(
2207 GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
2208 GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
2209 GPBCodedInputStreamState *state = &input->state_;
2210 id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax);
2211 switch (GPBGetFieldDataType(field)) {
2212#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \
2213 case GPBDataType##NAME: { \
2214 TYPE val = GPBCodedInputStreamRead##NAME(state); \
2215 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \
2216 break; \
2217 }
2218#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \
2219 case GPBDataType##NAME: { \
2220 id val = GPBCodedInputStreamReadRetained##NAME(state); \
2221 [(NSMutableArray*)genericArray addObject:val]; \
2222 [val release]; \
2223 break; \
2224 }
2225 CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool)
2226 CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32)
2227 CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32)
2228 CASE_REPEATED_NOT_PACKED_POD(Float, float, Float)
2229 CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64)
2230 CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64)
2231 CASE_REPEATED_NOT_PACKED_POD(Double, double, Double)
2232 CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32)
2233 CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64)
2234 CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32)
2235 CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64)
2236 CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32)
2237 CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64)
2238 CASE_REPEATED_NOT_PACKED_OBJECT(Bytes)
2239 CASE_REPEATED_NOT_PACKED_OBJECT(String)
2240#undef CASE_REPEATED_NOT_PACKED_POD
2241#undef CASE_NOT_PACKED_OBJECT
2242 case GPBDataTypeMessage: {
2243 GPBMessage *message = [[field.msgClass alloc] init];
2244 [input readMessage:message extensionRegistry:extensionRegistry];
2245 [(NSMutableArray*)genericArray addObject:message];
2246 [message release];
2247 break;
2248 }
2249 case GPBDataTypeGroup: {
2250 GPBMessage *message = [[field.msgClass alloc] init];
2251 [input readGroup:GPBFieldNumber(field)
2252 message:message
2253 extensionRegistry:extensionRegistry];
2254 [(NSMutableArray*)genericArray addObject:message];
2255 [message release];
2256 break;
2257 }
2258 case GPBDataTypeEnum: {
2259 int32_t val = GPBCodedInputStreamReadEnum(state);
2260 if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
2261 [field isValidEnumValue:val]) {
2262 [(GPBEnumArray*)genericArray addRawValue:val];
2263 } else {
2264 GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2265 [unknownFields mergeVarintField:GPBFieldNumber(field) value:val];
2266 }
2267 break;
2268 }
2269 } // switch
2270}
2271
2272- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
2273 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
2274 GPBDescriptor *descriptor = [self descriptor];
2275 GPBFileSyntax syntax = descriptor.file.syntax;
2276 GPBCodedInputStreamState *state = &input->state_;
2277 uint32_t tag = 0;
2278 NSUInteger startingIndex = 0;
2279 NSArray *fields = descriptor->fields_;
2280 NSUInteger numFields = fields.count;
2281 while (YES) {
2282 BOOL merged = NO;
2283 tag = GPBCodedInputStreamReadTag(state);
2284 for (NSUInteger i = 0; i < numFields; ++i) {
2285 if (startingIndex >= numFields) startingIndex = 0;
2286 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2287 if (GPBFieldTag(fieldDescriptor) == tag) {
2288 GPBFieldType fieldType = fieldDescriptor.fieldType;
2289 if (fieldType == GPBFieldTypeSingle) {
2290 MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax,
2291 input, extensionRegistry);
2292 // Well formed protos will only have a single field once, advance
2293 // the starting index to the next field.
2294 startingIndex += 1;
2295 } else if (fieldType == GPBFieldTypeRepeated) {
2296 if (fieldDescriptor.isPackable) {
2297 MergeRepeatedPackedFieldFromCodedInputStream(
2298 self, fieldDescriptor, syntax, input);
2299 // Well formed protos will only have a repeated field that is
2300 // packed once, advance the starting index to the next field.
2301 startingIndex += 1;
2302 } else {
2303 MergeRepeatedNotPackedFieldFromCodedInputStream(
2304 self, fieldDescriptor, syntax, input, extensionRegistry);
2305 }
2306 } else { // fieldType == GPBFieldTypeMap
2307 // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
2308 // point.
2309 id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax);
2310 [input readMapEntry:map
2311 extensionRegistry:extensionRegistry
2312 field:fieldDescriptor
2313 parentMessage:self];
2314 }
2315 merged = YES;
2316 break;
2317 } else {
2318 startingIndex += 1;
2319 }
2320 } // for(i < numFields)
2321
2322 if (!merged) {
2323 // Primitive, repeated types can be packed on unpacked on the wire, and
2324 // are parsed either way. The above loop covered tag in the preferred
2325 // for, so this need to check the alternate form.
2326 for (NSUInteger i = 0; i < numFields; ++i) {
2327 if (startingIndex >= numFields) startingIndex = 0;
2328 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2329 if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
2330 !GPBFieldDataTypeIsObject(fieldDescriptor) &&
2331 (GPBFieldAlternateTag(fieldDescriptor) == tag)) {
2332 BOOL alternateIsPacked = !fieldDescriptor.isPackable;
2333 if (alternateIsPacked) {
2334 MergeRepeatedPackedFieldFromCodedInputStream(
2335 self, fieldDescriptor, syntax, input);
2336 // Well formed protos will only have a repeated field that is
2337 // packed once, advance the starting index to the next field.
2338 startingIndex += 1;
2339 } else {
2340 MergeRepeatedNotPackedFieldFromCodedInputStream(
2341 self, fieldDescriptor, syntax, input, extensionRegistry);
2342 }
2343 merged = YES;
2344 break;
2345 } else {
2346 startingIndex += 1;
2347 }
2348 }
2349 }
2350
2351 if (!merged) {
2352 if (tag == 0) {
2353 // zero signals EOF / limit reached
2354 return;
2355 } else {
2356 if (GPBPreserveUnknownFields(syntax)) {
2357 if (![self parseUnknownField:input
2358 extensionRegistry:extensionRegistry
2359 tag:tag]) {
2360 // it's an endgroup tag
2361 return;
2362 }
2363 } else {
2364 if (![input skipField:tag]) {
2365 return;
2366 }
2367 }
2368 }
2369 } // if(!merged)
2370
2371 } // while(YES)
2372}
2373
2374#pragma mark - MergeFrom Support
2375
2376- (void)mergeFrom:(GPBMessage *)other {
2377 Class selfClass = [self class];
2378 Class otherClass = [other class];
2379 if (!([selfClass isSubclassOfClass:otherClass] ||
2380 [otherClass isSubclassOfClass:selfClass])) {
2381 [NSException raise:NSInvalidArgumentException
2382 format:@"Classes must match %@ != %@", selfClass, otherClass];
2383 }
2384
2385 // We assume something will be done and become visible.
2386 GPBBecomeVisibleToAutocreator(self);
2387
2388 GPBDescriptor *descriptor = [[self class] descriptor];
2389 GPBFileSyntax syntax = descriptor.file.syntax;
2390
2391 for (GPBFieldDescriptor *field in descriptor->fields_) {
2392 GPBFieldType fieldType = field.fieldType;
2393 if (fieldType == GPBFieldTypeSingle) {
2394 int32_t hasIndex = GPBFieldHasIndex(field);
2395 uint32_t fieldNumber = GPBFieldNumber(field);
2396 if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) {
2397 // Other doesn't have the field set, on to the next.
2398 continue;
2399 }
2400 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2401 switch (fieldDataType) {
2402 case GPBDataTypeBool:
2403 GPBSetBoolIvarWithFieldInternal(
2404 self, field, GPBGetMessageBoolField(other, field), syntax);
2405 break;
2406 case GPBDataTypeSFixed32:
2407 case GPBDataTypeEnum:
2408 case GPBDataTypeInt32:
2409 case GPBDataTypeSInt32:
2410 GPBSetInt32IvarWithFieldInternal(
2411 self, field, GPBGetMessageInt32Field(other, field), syntax);
2412 break;
2413 case GPBDataTypeFixed32:
2414 case GPBDataTypeUInt32:
2415 GPBSetUInt32IvarWithFieldInternal(
2416 self, field, GPBGetMessageUInt32Field(other, field), syntax);
2417 break;
2418 case GPBDataTypeSFixed64:
2419 case GPBDataTypeInt64:
2420 case GPBDataTypeSInt64:
2421 GPBSetInt64IvarWithFieldInternal(
2422 self, field, GPBGetMessageInt64Field(other, field), syntax);
2423 break;
2424 case GPBDataTypeFixed64:
2425 case GPBDataTypeUInt64:
2426 GPBSetUInt64IvarWithFieldInternal(
2427 self, field, GPBGetMessageUInt64Field(other, field), syntax);
2428 break;
2429 case GPBDataTypeFloat:
2430 GPBSetFloatIvarWithFieldInternal(
2431 self, field, GPBGetMessageFloatField(other, field), syntax);
2432 break;
2433 case GPBDataTypeDouble:
2434 GPBSetDoubleIvarWithFieldInternal(
2435 self, field, GPBGetMessageDoubleField(other, field), syntax);
2436 break;
2437 case GPBDataTypeBytes:
2438 case GPBDataTypeString: {
2439 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2440 GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax);
2441 break;
2442 }
2443 case GPBDataTypeMessage:
2444 case GPBDataTypeGroup: {
2445 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2446 if (GPBGetHasIvar(self, hasIndex, fieldNumber)) {
2447 GPBMessage *message =
2448 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2449 [message mergeFrom:otherVal];
2450 } else {
2451 GPBMessage *message = [otherVal copy];
2452 GPBSetRetainedObjectIvarWithFieldInternal(self, field, message,
2453 syntax);
2454 }
2455 break;
2456 }
2457 } // switch()
2458 } else if (fieldType == GPBFieldTypeRepeated) {
2459 // In the case of a list, they need to be appended, and there is no
2460 // _hasIvar to worry about setting.
2461 id otherArray =
2462 GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2463 if (otherArray) {
2464 GPBDataType fieldDataType = field->description_->dataType;
2465 if (GPBDataTypeIsObject(fieldDataType)) {
2466 NSMutableArray *resultArray =
2467 GetOrCreateArrayIvarWithField(self, field, syntax);
2468 [resultArray addObjectsFromArray:otherArray];
2469 } else if (fieldDataType == GPBDataTypeEnum) {
2470 GPBEnumArray *resultArray =
2471 GetOrCreateArrayIvarWithField(self, field, syntax);
2472 [resultArray addRawValuesFromArray:otherArray];
2473 } else {
2474 // The array type doesn't matter, that all implment
2475 // -addValuesFromArray:.
2476 GPBInt32Array *resultArray =
2477 GetOrCreateArrayIvarWithField(self, field, syntax);
2478 [resultArray addValuesFromArray:otherArray];
2479 }
2480 }
2481 } else { // fieldType = GPBFieldTypeMap
2482 // In the case of a map, they need to be merged, and there is no
2483 // _hasIvar to worry about setting.
2484 id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2485 if (otherDict) {
2486 GPBDataType keyDataType = field.mapKeyDataType;
2487 GPBDataType valueDataType = field->description_->dataType;
2488 if (GPBDataTypeIsObject(keyDataType) &&
2489 GPBDataTypeIsObject(valueDataType)) {
2490 NSMutableDictionary *resultDict =
2491 GetOrCreateMapIvarWithField(self, field, syntax);
2492 [resultDict addEntriesFromDictionary:otherDict];
2493 } else if (valueDataType == GPBDataTypeEnum) {
2494 // The exact type doesn't matter, just need to know it is a
2495 // GPB*EnumDictionary.
2496 GPBInt32EnumDictionary *resultDict =
2497 GetOrCreateMapIvarWithField(self, field, syntax);
2498 [resultDict addRawEntriesFromDictionary:otherDict];
2499 } else {
2500 // The exact type doesn't matter, they all implement
2501 // -addEntriesFromDictionary:.
2502 GPBInt32Int32Dictionary *resultDict =
2503 GetOrCreateMapIvarWithField(self, field, syntax);
2504 [resultDict addEntriesFromDictionary:otherDict];
2505 }
2506 }
2507 } // if (fieldType)..else if...else
2508 } // for(fields)
2509
2510 // Unknown fields.
2511 if (!unknownFields_) {
2512 [self setUnknownFields:other.unknownFields];
2513 } else {
2514 [unknownFields_ mergeUnknownFields:other.unknownFields];
2515 }
2516
2517 // Extensions
2518
2519 if (other->extensionMap_.count == 0) {
2520 return;
2521 }
2522
2523 if (extensionMap_ == nil) {
2524 extensionMap_ =
2525 CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
2526 } else {
2527 for (GPBExtensionDescriptor *extension in other->extensionMap_) {
2528 id otherValue = [other->extensionMap_ objectForKey:extension];
2529 id value = [extensionMap_ objectForKey:extension];
2530 BOOL isMessageExtension = GPBExtensionIsMessage(extension);
2531
2532 if (extension.repeated) {
2533 NSMutableArray *list = value;
2534 if (list == nil) {
2535 list = [[NSMutableArray alloc] init];
2536 [extensionMap_ setObject:list forKey:extension];
2537 [list release];
2538 }
2539 if (isMessageExtension) {
2540 for (GPBMessage *otherListValue in otherValue) {
2541 GPBMessage *copiedValue = [otherListValue copy];
2542 [list addObject:copiedValue];
2543 [copiedValue release];
2544 }
2545 } else {
2546 [list addObjectsFromArray:otherValue];
2547 }
2548 } else {
2549 if (isMessageExtension) {
2550 if (value) {
2551 [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
2552 } else {
2553 GPBMessage *copiedValue = [otherValue copy];
2554 [extensionMap_ setObject:copiedValue forKey:extension];
2555 [copiedValue release];
2556 }
2557 } else {
2558 [extensionMap_ setObject:otherValue forKey:extension];
2559 }
2560 }
2561
2562 if (isMessageExtension && !extension.isRepeated) {
2563 GPBMessage *autocreatedValue =
2564 [[autocreatedExtensionMap_ objectForKey:extension] retain];
2565 // Must remove from the map before calling GPBClearMessageAutocreator()
2566 // so that GPBClearMessageAutocreator() knows its safe to clear.
2567 [autocreatedExtensionMap_ removeObjectForKey:extension];
2568 GPBClearMessageAutocreator(autocreatedValue);
2569 [autocreatedValue release];
2570 }
2571 }
2572 }
2573}
2574
2575#pragma mark - isEqual: & hash Support
2576
2577- (BOOL)isEqual:(GPBMessage *)other {
2578 if (other == self) {
2579 return YES;
2580 }
2581 if (![other isKindOfClass:[self class]] &&
2582 ![self isKindOfClass:[other class]]) {
2583 return NO;
2584 }
2585
2586 GPBDescriptor *descriptor = [[self class] descriptor];
2587 uint8_t *selfStorage = (uint8_t *)messageStorage_;
2588 uint8_t *otherStorage = (uint8_t *)other->messageStorage_;
2589
2590 for (GPBFieldDescriptor *field in descriptor->fields_) {
2591 if (GPBFieldIsMapOrArray(field)) {
2592 // In the case of a list or map, there is no _hasIvar to worry about.
2593 // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but
2594 // the type doesn't really matter as the objects all support -count and
2595 // -isEqual:.
2596 NSArray *resultMapOrArray =
2597 GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2598 NSArray *otherMapOrArray =
2599 GPBGetObjectIvarWithFieldNoAutocreate(other, field);
2600 // nil and empty are equal
2601 if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) {
2602 if (![resultMapOrArray isEqual:otherMapOrArray]) {
2603 return NO;
2604 }
2605 }
2606 } else { // Single field
2607 int32_t hasIndex = GPBFieldHasIndex(field);
2608 uint32_t fieldNum = GPBFieldNumber(field);
2609 BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum);
2610 BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum);
2611 if (selfHas != otherHas) {
2612 return NO; // Differing has values, not equal.
2613 }
2614 if (!selfHas) {
2615 // Same has values, was no, nothing else to check for this field.
2616 continue;
2617 }
2618 // Now compare the values.
2619 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2620 size_t fieldOffset = field->description_->offset;
2621 switch (fieldDataType) {
2622 case GPBDataTypeBool: {
2623 BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset];
2624 BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset];
2625 if (*selfValPtr != *otherValPtr) {
2626 return NO;
2627 }
2628 break;
2629 }
2630 case GPBDataTypeSFixed32:
2631 case GPBDataTypeInt32:
2632 case GPBDataTypeSInt32:
2633 case GPBDataTypeEnum:
2634 case GPBDataTypeFixed32:
2635 case GPBDataTypeUInt32:
2636 case GPBDataTypeFloat: {
2637 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
2638 // These are all 32bit, signed/unsigned doesn't matter for equality.
2639 uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset];
2640 uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset];
2641 if (*selfValPtr != *otherValPtr) {
2642 return NO;
2643 }
2644 break;
2645 }
2646 case GPBDataTypeSFixed64:
2647 case GPBDataTypeInt64:
2648 case GPBDataTypeSInt64:
2649 case GPBDataTypeFixed64:
2650 case GPBDataTypeUInt64:
2651 case GPBDataTypeDouble: {
2652 _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
2653 // These are all 64bit, signed/unsigned doesn't matter for equality.
2654 uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset];
2655 uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset];
2656 if (*selfValPtr != *otherValPtr) {
2657 return NO;
2658 }
2659 break;
2660 }
2661 case GPBDataTypeBytes:
2662 case GPBDataTypeString:
2663 case GPBDataTypeMessage:
2664 case GPBDataTypeGroup: {
2665 // Type doesn't matter here, they all implement -isEqual:.
2666 id *selfValPtr = (id *)&selfStorage[fieldOffset];
2667 id *otherValPtr = (id *)&otherStorage[fieldOffset];
2668 if (![*selfValPtr isEqual:*otherValPtr]) {
2669 return NO;
2670 }
2671 break;
2672 }
2673 } // switch()
2674 } // if(mapOrArray)...else
2675 } // for(fields)
2676
2677 // nil and empty are equal
2678 if (extensionMap_.count != 0 || other->extensionMap_.count != 0) {
2679 if (![extensionMap_ isEqual:other->extensionMap_]) {
2680 return NO;
2681 }
2682 }
2683
2684 // nil and empty are equal
2685 GPBUnknownFieldSet *otherUnknowns = other->unknownFields_;
2686 if ([unknownFields_ countOfFields] != 0 ||
2687 [otherUnknowns countOfFields] != 0) {
2688 if (![unknownFields_ isEqual:otherUnknowns]) {
2689 return NO;
2690 }
2691 }
2692
2693 return YES;
2694}
2695
2696// It is very difficult to implement a generic hash for ProtoBuf messages that
2697// will perform well. If you need hashing on your ProtoBufs (eg you are using
2698// them as dictionary keys) you will probably want to implement a ProtoBuf
2699// message specific hash as a category on your protobuf class. Do not make it a
2700// category on GPBMessage as you will conflict with this hash, and will possibly
2701// override hash for all generated protobufs. A good implementation of hash will
2702// be really fast, so we would recommend only hashing protobufs that have an
2703// identifier field of some kind that you can easily hash. If you implement
2704// hash, we would strongly recommend overriding isEqual: in your category as
2705// well, as the default implementation of isEqual: is extremely slow, and may
2706// drastically affect performance in large sets.
2707- (NSUInteger)hash {
2708 GPBDescriptor *descriptor = [[self class] descriptor];
2709 const NSUInteger prime = 19;
2710 uint8_t *storage = (uint8_t *)messageStorage_;
2711
2712 // Start with the descriptor and then mix it with some instance info.
2713 // Hopefully that will give a spread based on classes and what fields are set.
2714 NSUInteger result = (NSUInteger)descriptor;
2715
2716 for (GPBFieldDescriptor *field in descriptor->fields_) {
2717 if (GPBFieldIsMapOrArray(field)) {
2718 // Exact type doesn't matter, just check if there are any elements.
2719 NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
2720 NSUInteger count = mapOrArray.count;
2721 if (count) {
2722 // NSArray/NSDictionary use count, use the field number and the count.
2723 result = prime * result + GPBFieldNumber(field);
2724 result = prime * result + count;
2725 }
2726 } else if (GPBGetHasIvarField(self, field)) {
2727 // Just using the field number seemed simple/fast, but then a small
2728 // message class where all the same fields are always set (to different
2729 // things would end up all with the same hash, so pull in some data).
2730 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2731 size_t fieldOffset = field->description_->offset;
2732 switch (fieldDataType) {
2733 case GPBDataTypeBool: {
2734 BOOL *valPtr = (BOOL *)&storage[fieldOffset];
2735 result = prime * result + *valPtr;
2736 break;
2737 }
2738 case GPBDataTypeSFixed32:
2739 case GPBDataTypeInt32:
2740 case GPBDataTypeSInt32:
2741 case GPBDataTypeEnum:
2742 case GPBDataTypeFixed32:
2743 case GPBDataTypeUInt32:
2744 case GPBDataTypeFloat: {
2745 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits);
2746 // These are all 32bit, just mix it in.
2747 uint32_t *valPtr = (uint32_t *)&storage[fieldOffset];
2748 result = prime * result + *valPtr;
2749 break;
2750 }
2751 case GPBDataTypeSFixed64:
2752 case GPBDataTypeInt64:
2753 case GPBDataTypeSInt64:
2754 case GPBDataTypeFixed64:
2755 case GPBDataTypeUInt64:
2756 case GPBDataTypeDouble: {
2757 _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits);
2758 // These are all 64bit, just mix what fits into an NSUInteger in.
2759 uint64_t *valPtr = (uint64_t *)&storage[fieldOffset];
2760 result = prime * result + (NSUInteger)(*valPtr);
2761 break;
2762 }
2763 case GPBDataTypeBytes:
2764 case GPBDataTypeString: {
2765 // Type doesn't matter here, they both implement -hash:.
2766 id *valPtr = (id *)&storage[fieldOffset];
2767 result = prime * result + [*valPtr hash];
2768 break;
2769 }
2770
2771 case GPBDataTypeMessage:
2772 case GPBDataTypeGroup: {
2773 GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset];
2774 // Could call -hash on the sub message, but that could recurse pretty
2775 // deep; follow the lead of NSArray/NSDictionary and don't really
2776 // recurse for hash, instead use the field number and the descriptor
2777 // of the sub message. Yes, this could suck for a bunch of messages
2778 // where they all only differ in the sub messages, but if you are
2779 // using a message with sub messages for something that needs -hash,
2780 // odds are you are also copying them as keys, and that deep copy
2781 // will also suck.
2782 result = prime * result + GPBFieldNumber(field);
2783 result = prime * result + (NSUInteger)[[*valPtr class] descriptor];
2784 break;
2785 }
2786 } // switch()
2787 }
2788 }
2789
2790 // Unknowns and extensions are not included.
2791
2792 return result;
2793}
2794
2795#pragma mark - Description Support
2796
2797- (NSString *)description {
2798 NSString *textFormat = GPBTextFormatForMessage(self, @" ");
2799 NSString *description = [NSString
2800 stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat];
2801 return description;
2802}
2803
2804#if DEBUG
2805
2806// Xcode 5.1 added support for custom quick look info.
2807// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1
2808- (id)debugQuickLookObject {
2809 return GPBTextFormatForMessage(self, nil);
2810}
2811
2812#endif // DEBUG
2813
2814#pragma mark - SerializedSize
2815
2816- (size_t)serializedSize {
2817 GPBDescriptor *descriptor = [[self class] descriptor];
2818 size_t result = 0;
2819
2820 // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate()
2821 // avoids doing the has check again.
2822
2823 // Fields.
2824 for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
2825 GPBFieldType fieldType = fieldDescriptor.fieldType;
2826 GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor);
2827
2828 // Single Fields
2829 if (fieldType == GPBFieldTypeSingle) {
2830 BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor);
2831 if (!selfHas) {
2832 continue; // Nothing to do.
2833 }
2834
2835 uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor);
2836
2837 switch (fieldDataType) {
2838#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \
2839 case GPBDataType##NAME: { \
2840 TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \
2841 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \
2842 break; \
2843 }
2844#define CASE_SINGLE_OBJECT(NAME) \
2845 case GPBDataType##NAME: { \
2846 id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \
2847 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \
2848 break; \
2849 }
2850 CASE_SINGLE_POD(Bool, BOOL, Bool)
2851 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32)
2852 CASE_SINGLE_POD(SFixed32, int32_t, Int32)
2853 CASE_SINGLE_POD(Float, float, Float)
2854 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64)
2855 CASE_SINGLE_POD(SFixed64, int64_t, Int64)
2856 CASE_SINGLE_POD(Double, double, Double)
2857 CASE_SINGLE_POD(Int32, int32_t, Int32)
2858 CASE_SINGLE_POD(Int64, int64_t, Int64)
2859 CASE_SINGLE_POD(SInt32, int32_t, Int32)
2860 CASE_SINGLE_POD(SInt64, int64_t, Int64)
2861 CASE_SINGLE_POD(UInt32, uint32_t, UInt32)
2862 CASE_SINGLE_POD(UInt64, uint64_t, UInt64)
2863 CASE_SINGLE_OBJECT(Bytes)
2864 CASE_SINGLE_OBJECT(String)
2865 CASE_SINGLE_OBJECT(Message)
2866 CASE_SINGLE_OBJECT(Group)
2867 CASE_SINGLE_POD(Enum, int32_t, Int32)
2868#undef CASE_SINGLE_POD
2869#undef CASE_SINGLE_OBJECT
2870 }
2871
2872 // Repeated Fields
2873 } else if (fieldType == GPBFieldTypeRepeated) {
2874 id genericArray =
2875 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
2876 NSUInteger count = [genericArray count];
2877 if (count == 0) {
2878 continue; // Nothing to add.
2879 }
2880 __block size_t dataSize = 0;
2881
2882 switch (fieldDataType) {
2883#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \
2884 CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, )
2885#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \
2886 case GPBDataType##NAME: { \
2887 GPB##ARRAY_TYPE##Array *array = genericArray; \
2888 [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \
2889 _Pragma("unused(idx, stop)"); \
2890 dataSize += GPBCompute##NAME##SizeNoTag(value); \
2891 }]; \
2892 break; \
2893 }
2894#define CASE_REPEATED_OBJECT(NAME) \
2895 case GPBDataType##NAME: { \
2896 for (id value in genericArray) { \
2897 dataSize += GPBCompute##NAME##SizeNoTag(value); \
2898 } \
2899 break; \
2900 }
2901 CASE_REPEATED_POD(Bool, BOOL, Bool)
2902 CASE_REPEATED_POD(Fixed32, uint32_t, UInt32)
2903 CASE_REPEATED_POD(SFixed32, int32_t, Int32)
2904 CASE_REPEATED_POD(Float, float, Float)
2905 CASE_REPEATED_POD(Fixed64, uint64_t, UInt64)
2906 CASE_REPEATED_POD(SFixed64, int64_t, Int64)
2907 CASE_REPEATED_POD(Double, double, Double)
2908 CASE_REPEATED_POD(Int32, int32_t, Int32)
2909 CASE_REPEATED_POD(Int64, int64_t, Int64)
2910 CASE_REPEATED_POD(SInt32, int32_t, Int32)
2911 CASE_REPEATED_POD(SInt64, int64_t, Int64)
2912 CASE_REPEATED_POD(UInt32, uint32_t, UInt32)
2913 CASE_REPEATED_POD(UInt64, uint64_t, UInt64)
2914 CASE_REPEATED_OBJECT(Bytes)
2915 CASE_REPEATED_OBJECT(String)
2916 CASE_REPEATED_OBJECT(Message)
2917 CASE_REPEATED_OBJECT(Group)
2918 CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw)
2919#undef CASE_REPEATED_POD
2920#undef CASE_REPEATED_POD_EXTRA
2921#undef CASE_REPEATED_OBJECT
2922 } // switch
2923 result += dataSize;
2924 size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor));
2925 if (fieldDataType == GPBDataTypeGroup) {
2926 // Groups have both a start and an end tag.
2927 tagSize *= 2;
2928 }
2929 if (fieldDescriptor.isPackable) {
2930 result += tagSize;
2931 result += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
2932 } else {
2933 result += count * tagSize;
2934 }
2935
2936 // Map<> Fields
2937 } else { // fieldType == GPBFieldTypeMap
2938 if (GPBDataTypeIsObject(fieldDataType) &&
2939 (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) {
2940 // If key type was string, then the map is an NSDictionary.
2941 NSDictionary *map =
2942 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
2943 if (map) {
2944 result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor);
2945 }
2946 } else {
2947 // Type will be GPB*GroupDictionary, exact type doesn't matter.
2948 GPBInt32Int32Dictionary *map =
2949 GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor);
2950 result += [map computeSerializedSizeAsField:fieldDescriptor];
2951 }
2952 }
2953 } // for(fields)
2954
2955 // Add any unknown fields.
2956 if (descriptor.wireFormat) {
2957 result += [unknownFields_ serializedSizeAsMessageSet];
2958 } else {
2959 result += [unknownFields_ serializedSize];
2960 }
2961
2962 // Add any extensions.
2963 for (GPBExtensionDescriptor *extension in extensionMap_) {
2964 id value = [extensionMap_ objectForKey:extension];
2965 result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value);
2966 }
2967
2968 return result;
2969}
2970
2971#pragma mark - Resolve Methods Support
2972
2973typedef struct ResolveIvarAccessorMethodResult {
2974 IMP impToAdd;
2975 SEL encodingSelector;
2976} ResolveIvarAccessorMethodResult;
2977
2978static void ResolveIvarGet(GPBFieldDescriptor *field,
2979 ResolveIvarAccessorMethodResult *result) {
2980 GPBDataType fieldDataType = GPBGetFieldDataType(field);
2981 switch (fieldDataType) {
2982#define CASE_GET(NAME, TYPE, TRUE_NAME) \
2983 case GPBDataType##NAME: { \
2984 result->impToAdd = imp_implementationWithBlock(^(id obj) { \
2985 return GPBGetMessage##TRUE_NAME##Field(obj, field); \
2986 }); \
2987 result->encodingSelector = @selector(get##NAME); \
2988 break; \
2989 }
2990#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \
2991 case GPBDataType##NAME: { \
2992 result->impToAdd = imp_implementationWithBlock(^(id obj) { \
2993 return GPBGetObjectIvarWithField(obj, field); \
2994 }); \
2995 result->encodingSelector = @selector(get##NAME); \
2996 break; \
2997 }
2998 CASE_GET(Bool, BOOL, Bool)
2999 CASE_GET(Fixed32, uint32_t, UInt32)
3000 CASE_GET(SFixed32, int32_t, Int32)
3001 CASE_GET(Float, float, Float)
3002 CASE_GET(Fixed64, uint64_t, UInt64)
3003 CASE_GET(SFixed64, int64_t, Int64)
3004 CASE_GET(Double, double, Double)
3005 CASE_GET(Int32, int32_t, Int32)
3006 CASE_GET(Int64, int64_t, Int64)
3007 CASE_GET(SInt32, int32_t, Int32)
3008 CASE_GET(SInt64, int64_t, Int64)
3009 CASE_GET(UInt32, uint32_t, UInt32)
3010 CASE_GET(UInt64, uint64_t, UInt64)
3011 CASE_GET_OBJECT(Bytes, id, Object)
3012 CASE_GET_OBJECT(String, id, Object)
3013 CASE_GET_OBJECT(Message, id, Object)
3014 CASE_GET_OBJECT(Group, id, Object)
3015 CASE_GET(Enum, int32_t, Enum)
3016#undef CASE_GET
3017 }
3018}
3019
3020static void ResolveIvarSet(GPBFieldDescriptor *field,
3021 GPBFileSyntax syntax,
3022 ResolveIvarAccessorMethodResult *result) {
3023 GPBDataType fieldDataType = GPBGetFieldDataType(field);
3024 switch (fieldDataType) {
3025#define CASE_SET(NAME, TYPE, TRUE_NAME) \
3026 case GPBDataType##NAME: { \
3027 result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \
3028 return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \
3029 }); \
3030 result->encodingSelector = @selector(set##NAME:); \
3031 break; \
3032 }
3033 CASE_SET(Bool, BOOL, Bool)
3034 CASE_SET(Fixed32, uint32_t, UInt32)
3035 CASE_SET(SFixed32, int32_t, Int32)
3036 CASE_SET(Float, float, Float)
3037 CASE_SET(Fixed64, uint64_t, UInt64)
3038 CASE_SET(SFixed64, int64_t, Int64)
3039 CASE_SET(Double, double, Double)
3040 CASE_SET(Int32, int32_t, Int32)
3041 CASE_SET(Int64, int64_t, Int64)
3042 CASE_SET(SInt32, int32_t, Int32)
3043 CASE_SET(SInt64, int64_t, Int64)
3044 CASE_SET(UInt32, uint32_t, UInt32)
3045 CASE_SET(UInt64, uint64_t, UInt64)
3046 CASE_SET(Bytes, id, Object)
3047 CASE_SET(String, id, Object)
3048 CASE_SET(Message, id, Object)
3049 CASE_SET(Group, id, Object)
3050 CASE_SET(Enum, int32_t, Enum)
3051#undef CASE_SET
3052 }
3053}
3054
3055+ (BOOL)resolveInstanceMethod:(SEL)sel {
3056 const GPBDescriptor *descriptor = [self descriptor];
3057 if (!descriptor) {
3058 return NO;
3059 }
3060
3061 // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given
3062 // message should not have has support (done in GPBDescriptor.m), so there is
3063 // no need for checks here to see if has*/setHas* are allowed.
3064
3065 ResolveIvarAccessorMethodResult result = {NULL, NULL};
3066 for (GPBFieldDescriptor *field in descriptor->fields_) {
3067 BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
3068 if (!isMapOrArray) {
3069 // Single fields.
3070 if (sel == field->getSel_) {
3071 ResolveIvarGet(field, &result);
3072 break;
3073 } else if (sel == field->setSel_) {
3074 ResolveIvarSet(field, descriptor.file.syntax, &result);
3075 break;
3076 } else if (sel == field->hasOrCountSel_) {
3077 int32_t index = GPBFieldHasIndex(field);
3078 uint32_t fieldNum = GPBFieldNumber(field);
3079 result.impToAdd = imp_implementationWithBlock(^(id obj) {
3080 return GPBGetHasIvar(obj, index, fieldNum);
3081 });
3082 result.encodingSelector = @selector(getBool);
3083 break;
3084 } else if (sel == field->setHasSel_) {
3085 result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
3086 if (value) {
3087 [NSException raise:NSInvalidArgumentException
3088 format:@"%@: %@ can only be set to NO (to clear field).",
3089 [obj class],
3090 NSStringFromSelector(field->setHasSel_)];
3091 }
3092 GPBClearMessageField(obj, field);
3093 });
3094 result.encodingSelector = @selector(setBool:);
3095 break;
3096 } else {
3097 GPBOneofDescriptor *oneof = field->containingOneof_;
3098 if (oneof && (sel == oneof->caseSel_)) {
3099 int32_t index = oneof->oneofDescription_->index;
3100 result.impToAdd = imp_implementationWithBlock(^(id obj) {
3101 return GPBGetHasOneof(obj, index);
3102 });
3103 result.encodingSelector = @selector(getEnum);
3104 break;
3105 }
3106 }
3107 } else {
3108 // map<>/repeated fields.
3109 if (sel == field->getSel_) {
3110 if (field.fieldType == GPBFieldTypeRepeated) {
3111 result.impToAdd = imp_implementationWithBlock(^(id obj) {
3112 return GetArrayIvarWithField(obj, field);
3113 });
3114 } else {
3115 result.impToAdd = imp_implementationWithBlock(^(id obj) {
3116 return GetMapIvarWithField(obj, field);
3117 });
3118 }
3119 result.encodingSelector = @selector(getArray);
3120 break;
3121 } else if (sel == field->setSel_) {
3122 // Local for syntax so the block can directly capture it and not the
3123 // full lookup.
3124 const GPBFileSyntax syntax = descriptor.file.syntax;
3125 result.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
3126 return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
3127 });
3128 result.encodingSelector = @selector(setArray:);
3129 break;
3130 } else if (sel == field->hasOrCountSel_) {
3131 result.impToAdd = imp_implementationWithBlock(^(id obj) {
3132 // Type doesn't matter, all *Array and *Dictionary types support
3133 // -count.
3134 NSArray *arrayOrMap =
3135 GPBGetObjectIvarWithFieldNoAutocreate(obj, field);
3136 return [arrayOrMap count];
3137 });
3138 result.encodingSelector = @selector(getArrayCount);
3139 break;
3140 }
3141 }
3142 }
3143 if (result.impToAdd) {
3144 const char *encoding =
3145 GPBMessageEncodingForSelector(result.encodingSelector, YES);
3146 BOOL methodAdded = class_addMethod(descriptor.messageClass, sel,
3147 result.impToAdd, encoding);
3148 return methodAdded;
3149 }
3150 return [super resolveInstanceMethod:sel];
3151}
3152
3153+ (BOOL)resolveClassMethod:(SEL)sel {
3154 // Extensions scoped to a Message and looked up via class methods.
3155 if (GPBResolveExtensionClassMethod(self, sel)) {
3156 return YES;
3157 }
3158 return [super resolveClassMethod:sel];
3159}
3160
3161#pragma mark - NSCoding Support
3162
3163+ (BOOL)supportsSecureCoding {
3164 return YES;
3165}
3166
3167- (instancetype)initWithCoder:(NSCoder *)aDecoder {
3168 self = [self init];
3169 if (self) {
3170 NSData *data =
3171 [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey];
3172 if (data.length) {
3173 [self mergeFromData:data extensionRegistry:nil];
3174 }
3175 }
3176 return self;
3177}
3178
3179- (void)encodeWithCoder:(NSCoder *)aCoder {
3180 NSData *data = [self data];
3181 if (data.length) {
3182 [aCoder encodeObject:data forKey:kGPBDataCoderKey];
3183 }
3184}
3185
3186#pragma mark - KVC Support
3187
3188+ (BOOL)accessInstanceVariablesDirectly {
3189 // Make sure KVC doesn't use instance variables.
3190 return NO;
3191}
3192
3193@end