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