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

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

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