Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: third_party/protobuf/objectivec/GPBMessage.m

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

Powered by Google App Engine
This is Rietveld 408576698