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