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