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