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