1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file or at 6// https://developers.google.com/open-source/licenses/bsd 7 8#import "GPBMessage.h" 9#import "GPBMessage_PackagePrivate.h" 10 11#import <Foundation/Foundation.h> 12#import <objc/message.h> 13#import <objc/runtime.h> 14#import <os/lock.h> 15#import <stdatomic.h> 16 17#import "GPBArray.h" 18#import "GPBArray_PackagePrivate.h" 19#import "GPBCodedInputStream.h" 20#import "GPBCodedInputStream_PackagePrivate.h" 21#import "GPBCodedOutputStream.h" 22#import "GPBCodedOutputStream_PackagePrivate.h" 23#import "GPBDescriptor.h" 24#import "GPBDescriptor_PackagePrivate.h" 25#import "GPBDictionary.h" 26#import "GPBDictionary_PackagePrivate.h" 27#import "GPBExtensionInternals.h" 28#import "GPBExtensionRegistry.h" 29#import "GPBRootObject.h" 30#import "GPBRootObject_PackagePrivate.h" 31#import "GPBUnknownField.h" 32#import "GPBUnknownFieldSet.h" 33#import "GPBUnknownFieldSet_PackagePrivate.h" 34#import "GPBUnknownFields.h" 35#import "GPBUnknownFields_PackagePrivate.h" 36#import "GPBUtilities.h" 37#import "GPBUtilities_PackagePrivate.h" 38 39// TODO: Consider using on other functions to reduce bloat when 40// some compiler optimizations are enabled. 41#define GPB_NOINLINE __attribute__((noinline)) 42 43// Returns a new instance that was automatically created by |autocreator| for 44// its field |field|. 45static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator, 46 GPBFieldDescriptor *field) 47 __attribute__((ns_returns_retained)); 48 49// Direct access is use for speed, to avoid even internally declaring things 50// read/write, etc. The warning is enabled in the project to ensure code calling 51// protos can turn on -Wdirect-ivar-access without issues. 52#pragma clang diagnostic push 53#pragma clang diagnostic ignored "-Wdirect-ivar-access" 54 55NSString *const GPBMessageErrorDomain = GPBNSStringifySymbol(GPBMessageErrorDomain); 56 57NSString *const GPBErrorReasonKey = @"Reason"; 58 59static NSString *const kGPBDataCoderKey = @"GPBData"; 60 61// Length-delimited has a max size of 2GB, and thus messages do also. 62// src/google/protobuf/message_lite also does this enforcement on the C++ side. Validation for 63// parsing is done with GPBCodedInputStream; but for messages, it is less checks to do it within 64// the message side since the input stream code calls these same bottlenecks. 65// https://protobuf.dev/programming-guides/encoding/#cheat-sheet 66static const size_t kMaximumMessageSize = 0x7fffffff; 67 68NSString *const GPBMessageExceptionMessageTooLarge = 69 GPBNSStringifySymbol(GPBMessageExceptionMessageTooLarge); 70 71// 72// PLEASE REMEMBER: 73// 74// This is the base class for *all* messages generated, so any selector defined, 75// *public* or *private* could end up colliding with a proto message field. So 76// avoid using selectors that could match a property, use C functions to hide 77// them, etc. 78// 79 80@interface GPBMessage () { 81 @package 82 // Only one of these two is ever set, GPBUnknownFieldSet is being deprecated and will 83 // eventually be removed, but because that api support mutation, once the property is 84 // fetch it must continue to be used so any mutations will be honored in future operations 85 // on the message. 86 // Read only operations that access these two/cause things to migration between them should 87 // be protected with an @synchronized(self) block (that way the code also doesn't have to 88 // worry about throws). 89 NSMutableData *unknownFieldData_; 90#pragma clang diagnostic push 91#pragma clang diagnostic ignored "-Wdeprecated-declarations" 92 GPBUnknownFieldSet *unknownFields_; 93#pragma clang diagnostic pop 94 95 NSMutableDictionary *extensionMap_; 96 // Readonly access to autocreatedExtensionMap_ is protected via readOnlyLock_. 97 NSMutableDictionary *autocreatedExtensionMap_; 98 99 // If the object was autocreated, we remember the creator so that if we get 100 // mutated, we can inform the creator to make our field visible. 101 GPBMessage *autocreator_; 102 GPBFieldDescriptor *autocreatorField_; 103 GPBExtensionDescriptor *autocreatorExtension_; 104 105 // Messages can only be mutated from one thread. But some *readonly* operations modify internal 106 // state because they autocreate things. The autocreatedExtensionMap_ is one such structure. 107 // Access during readonly operations is protected via this lock. 108 // 109 // Long ago, this was an OSSpinLock, but then it came to light that there were issues for that on 110 // iOS: 111 // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ 112 // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html 113 // It was changed to a dispatch_semaphore_t, but that has potential for priority inversion issues. 114 // The minOS versions are now high enough that os_unfair_lock can be used, and should provide 115 // all the support we need. For more information in the concurrency/locking space see: 116 // https://gist.github.com/tclementdev/6af616354912b0347cdf6db159c37057 117 // https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html 118 // https://developer.apple.com/videos/play/wwdc2017/706/ 119 os_unfair_lock readOnlyLock_; 120} 121@end 122 123static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) 124 __attribute__((ns_returns_retained)); 125static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 126static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 127static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) 128 __attribute__((ns_returns_retained)); 129static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 130static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 131static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) 132 __attribute__((ns_returns_retained)); 133 134#if defined(DEBUG) && DEBUG 135static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { 136 return [NSError errorWithDomain:GPBMessageErrorDomain code:code userInfo:userInfo]; 137} 138#endif 139 140static NSError *ErrorFromException(NSException *exception) { 141 NSError *error = nil; 142 143 if ([exception.name isEqual:GPBCodedInputStreamException]) { 144 NSDictionary *exceptionInfo = exception.userInfo; 145 error = exceptionInfo[GPBCodedInputStreamUnderlyingErrorKey]; 146 } 147 148 if (!error) { 149 NSString *reason = exception.reason; 150 NSDictionary *userInfo = nil; 151 if ([reason length]) { 152 userInfo = @{GPBErrorReasonKey : reason}; 153 } 154 155 error = [NSError errorWithDomain:GPBMessageErrorDomain 156 code:GPBMessageErrorCodeOther 157 userInfo:userInfo]; 158 } 159 return error; 160} 161 162// Helper to encode varints onto the mutable data, the max size need is 10 bytes. 163GPB_NOINLINE 164static uint8_t *EncodeVarintU64(uint64_t val, uint8_t *ptr) { 165 do { 166 uint8_t byte = val & 0x7fU; 167 val >>= 7; 168 if (val) byte |= 0x80U; 169 *(ptr++) = byte; 170 } while (val); 171 return ptr; 172} 173 174// Helper to encode varints onto the mutable data, the max size need is 5 bytes. 175GPB_NOINLINE 176static uint8_t *EncodeVarintU32(uint32_t val, uint8_t *ptr) { 177 do { 178 uint8_t byte = val & 0x7fU; 179 val >>= 7; 180 if (val) byte |= 0x80U; 181 *(ptr++) = byte; 182 } while (val); 183 return ptr; 184} 185 186// Helper to encode signed int32 values as varints onto the mutable data, the max size need is 10 187// bytes. 188GPB_NOINLINE 189static uint8_t *EncodeVarintS32(int32_t val, uint8_t *ptr) { 190 if (val >= 0) { 191 return EncodeVarintU32((uint32_t)val, ptr); 192 } else { 193 // Must sign-extend 194 int64_t extended = val; 195 return EncodeVarintU64((uint64_t)extended, ptr); 196 } 197} 198 199GPB_NOINLINE 200static void AddUnknownFieldVarint32(GPBMessage *self, uint32_t fieldNumber, int32_t value) { 201 if (self->unknownFields_) { 202 [self->unknownFields_ mergeVarintField:fieldNumber value:value]; 203 return; 204 } 205 uint8_t buf[20]; 206 uint8_t *ptr = buf; 207 ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint), ptr); 208 ptr = EncodeVarintS32(value, ptr); 209 210 if (self->unknownFieldData_ == nil) { 211 self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:ptr - buf]; 212 GPBBecomeVisibleToAutocreator(self); 213 } 214 [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; 215} 216 217GPB_NOINLINE 218static void AddUnknownFieldLengthDelimited(GPBMessage *self, uint32_t fieldNumber, NSData *value) { 219 if (self->unknownFields_) { 220 [self->unknownFields_ mergeLengthDelimited:fieldNumber value:value]; 221 return; 222 } 223 uint8_t buf[20]; 224 uint8_t *ptr = buf; 225 ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatLengthDelimited), ptr); 226 ptr = EncodeVarintU64((uint64_t)value.length, ptr); 227 228 if (self->unknownFieldData_ == nil) { 229 self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(ptr - buf) + value.length]; 230 GPBBecomeVisibleToAutocreator(self); 231 } 232 [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; 233 [self->unknownFieldData_ appendData:value]; 234} 235 236GPB_NOINLINE 237static void AddUnknownMessageSetEntry(GPBMessage *self, uint32_t typeId, NSData *value) { 238 if (self->unknownFields_) { 239 // Legacy Set does this odd storage for MessageSet. 240 [self->unknownFields_ mergeLengthDelimited:typeId value:value]; 241 return; 242 } 243 244 uint8_t buf[60]; 245 uint8_t *ptr = buf; 246 ptr = EncodeVarintU32(GPBWireFormatMessageSetItemTag, ptr); 247 ptr = EncodeVarintU32(GPBWireFormatMessageSetTypeIdTag, ptr); 248 ptr = EncodeVarintU32(typeId, ptr); 249 ptr = EncodeVarintU32(GPBWireFormatMessageSetMessageTag, ptr); 250 ptr = EncodeVarintU64((uint64_t)value.length, ptr); 251 uint8_t *split = ptr; 252 253 ptr = EncodeVarintU32(GPBWireFormatMessageSetItemEndTag, ptr); 254 uint8_t *end = ptr; 255 256 if (self->unknownFieldData_ == nil) { 257 self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(end - buf) + value.length]; 258 GPBBecomeVisibleToAutocreator(self); 259 } 260 [self->unknownFieldData_ appendBytes:buf length:split - buf]; 261 [self->unknownFieldData_ appendData:value]; 262 [self->unknownFieldData_ appendBytes:split length:end - split]; 263} 264 265GPB_NOINLINE 266static void ParseUnknownField(GPBMessage *self, uint32_t tag, GPBCodedInputStream *input) { 267 if (self->unknownFields_) { 268 if (![self->unknownFields_ mergeFieldFrom:tag input:input]) { 269 GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag"); 270 } 271 return; 272 } 273 274 uint8_t buf[20]; 275 uint8_t *ptr = buf; 276 ptr = EncodeVarintU32(tag, ptr); // All will need the tag 277 NSData *bytesToAppend = nil; 278 279 GPBCodedInputStreamState *state = &input->state_; 280 281 switch (GPBWireFormatGetTagWireType(tag)) { 282 case GPBWireFormatVarint: { 283 ptr = EncodeVarintU64(GPBCodedInputStreamReadUInt64(state), ptr); 284 break; 285 } 286 case GPBWireFormatFixed64: { 287 uint64_t value = GPBCodedInputStreamReadFixed64(state); 288 *(ptr++) = (uint8_t)(value) & 0xFF; 289 *(ptr++) = (uint8_t)(value >> 8) & 0xFF; 290 *(ptr++) = (uint8_t)(value >> 16) & 0xFF; 291 *(ptr++) = (uint8_t)(value >> 24) & 0xFF; 292 *(ptr++) = (uint8_t)(value >> 32) & 0xFF; 293 *(ptr++) = (uint8_t)(value >> 40) & 0xFF; 294 *(ptr++) = (uint8_t)(value >> 48) & 0xFF; 295 *(ptr++) = (uint8_t)(value >> 56) & 0xFF; 296 break; 297 } 298 case GPBWireFormatLengthDelimited: { 299 bytesToAppend = GPBCodedInputStreamReadRetainedBytes(state); 300 ptr = EncodeVarintU64((uint64_t)bytesToAppend.length, ptr); 301 break; 302 } 303 case GPBWireFormatStartGroup: { 304 bytesToAppend = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy( 305 state, GPBWireFormatGetTagFieldNumber(tag)); 306 break; 307 } 308 case GPBWireFormatEndGroup: 309 GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag"); 310 break; 311 case GPBWireFormatFixed32: { 312 uint32_t value = GPBCodedInputStreamReadFixed32(state); 313 *(ptr++) = (uint8_t)(value) & 0xFF; 314 *(ptr++) = (uint8_t)(value >> 8) & 0xFF; 315 *(ptr++) = (uint8_t)(value >> 16) & 0xFF; 316 *(ptr++) = (uint8_t)(value >> 24) & 0xFF; 317 break; 318 } 319 } 320 321 if (self->unknownFieldData_ == nil) { 322 self->unknownFieldData_ = 323 [[NSMutableData alloc] initWithCapacity:(ptr - buf) + bytesToAppend.length]; 324 GPBBecomeVisibleToAutocreator(self); 325 } 326 327 [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; 328 if (bytesToAppend) { 329 [self->unknownFieldData_ appendData:bytesToAppend]; 330 [bytesToAppend release]; 331 } 332} 333 334static void CheckExtension(GPBMessage *self, GPBExtensionDescriptor *extension) { 335 if (![self isKindOfClass:extension.containingMessageClass]) { 336 [NSException raise:NSInvalidArgumentException 337 format:@"Extension %@ used on wrong class (%@ instead of %@)", 338 extension.singletonName, [self class], extension.containingMessageClass]; 339 } 340} 341 342static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) { 343 if (extensionMap.count == 0) { 344 return nil; 345 } 346 NSMutableDictionary *result = 347 [[NSMutableDictionary allocWithZone:zone] initWithCapacity:extensionMap.count]; 348 349 for (GPBExtensionDescriptor *extension in extensionMap) { 350 id value = [extensionMap objectForKey:extension]; 351 BOOL isMessageExtension = GPBExtensionIsMessage(extension); 352 353 if (extension.repeated) { 354 if (isMessageExtension) { 355 NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:[value count]]; 356 for (GPBMessage *listValue in value) { 357 GPBMessage *copiedValue = [listValue copyWithZone:zone]; 358 [list addObject:copiedValue]; 359 [copiedValue release]; 360 } 361 [result setObject:list forKey:extension]; 362 [list release]; 363 } else { 364 NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; 365 [result setObject:copiedValue forKey:extension]; 366 [copiedValue release]; 367 } 368 } else { 369 if (isMessageExtension) { 370 GPBMessage *copiedValue = [value copyWithZone:zone]; 371 [result setObject:copiedValue forKey:extension]; 372 [copiedValue release]; 373 } else { 374 [result setObject:value forKey:extension]; 375 } 376 } 377 } 378 379 return result; 380} 381 382static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { 383 id result; 384 GPBDataType fieldDataType = GPBGetFieldDataType(field); 385 switch (fieldDataType) { 386 case GPBDataTypeBool: 387 result = [[GPBBoolArray alloc] init]; 388 break; 389 case GPBDataTypeFixed32: 390 case GPBDataTypeUInt32: 391 result = [[GPBUInt32Array alloc] init]; 392 break; 393 case GPBDataTypeInt32: 394 case GPBDataTypeSFixed32: 395 case GPBDataTypeSInt32: 396 result = [[GPBInt32Array alloc] init]; 397 break; 398 case GPBDataTypeFixed64: 399 case GPBDataTypeUInt64: 400 result = [[GPBUInt64Array alloc] init]; 401 break; 402 case GPBDataTypeInt64: 403 case GPBDataTypeSFixed64: 404 case GPBDataTypeSInt64: 405 result = [[GPBInt64Array alloc] init]; 406 break; 407 case GPBDataTypeFloat: 408 result = [[GPBFloatArray alloc] init]; 409 break; 410 case GPBDataTypeDouble: 411 result = [[GPBDoubleArray alloc] init]; 412 break; 413 414 case GPBDataTypeEnum: 415 result = [[GPBEnumArray alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; 416 break; 417 418 case GPBDataTypeBytes: 419 case GPBDataTypeGroup: 420 case GPBDataTypeMessage: 421 case GPBDataTypeString: 422 if (autocreator) { 423 result = [[GPBAutocreatedArray alloc] init]; 424 } else { 425 result = [[NSMutableArray alloc] init]; 426 } 427 break; 428 } 429 430 if (autocreator) { 431 if (GPBDataTypeIsObject(fieldDataType)) { 432 GPBAutocreatedArray *autoArray = result; 433 autoArray->_autocreator = autocreator; 434 } else { 435 GPBInt32Array *gpbArray = result; 436 gpbArray->_autocreator = autocreator; 437 } 438 } 439 440 return result; 441} 442 443static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { 444 id result; 445 GPBDataType keyDataType = field.mapKeyDataType; 446 GPBDataType valueDataType = GPBGetFieldDataType(field); 447 switch (keyDataType) { 448 case GPBDataTypeBool: 449 switch (valueDataType) { 450 case GPBDataTypeBool: 451 result = [[GPBBoolBoolDictionary alloc] init]; 452 break; 453 case GPBDataTypeFixed32: 454 case GPBDataTypeUInt32: 455 result = [[GPBBoolUInt32Dictionary alloc] init]; 456 break; 457 case GPBDataTypeInt32: 458 case GPBDataTypeSFixed32: 459 case GPBDataTypeSInt32: 460 result = [[GPBBoolInt32Dictionary alloc] init]; 461 break; 462 case GPBDataTypeFixed64: 463 case GPBDataTypeUInt64: 464 result = [[GPBBoolUInt64Dictionary alloc] init]; 465 break; 466 case GPBDataTypeInt64: 467 case GPBDataTypeSFixed64: 468 case GPBDataTypeSInt64: 469 result = [[GPBBoolInt64Dictionary alloc] init]; 470 break; 471 case GPBDataTypeFloat: 472 result = [[GPBBoolFloatDictionary alloc] init]; 473 break; 474 case GPBDataTypeDouble: 475 result = [[GPBBoolDoubleDictionary alloc] init]; 476 break; 477 case GPBDataTypeEnum: 478 result = [[GPBBoolEnumDictionary alloc] 479 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 480 break; 481 case GPBDataTypeBytes: 482 case GPBDataTypeMessage: 483 case GPBDataTypeString: 484 result = [[GPBBoolObjectDictionary alloc] init]; 485 break; 486 case GPBDataTypeGroup: 487 NSCAssert(NO, @"shouldn't happen"); 488 return nil; 489 } 490 break; 491 case GPBDataTypeFixed32: 492 case GPBDataTypeUInt32: 493 switch (valueDataType) { 494 case GPBDataTypeBool: 495 result = [[GPBUInt32BoolDictionary alloc] init]; 496 break; 497 case GPBDataTypeFixed32: 498 case GPBDataTypeUInt32: 499 result = [[GPBUInt32UInt32Dictionary alloc] init]; 500 break; 501 case GPBDataTypeInt32: 502 case GPBDataTypeSFixed32: 503 case GPBDataTypeSInt32: 504 result = [[GPBUInt32Int32Dictionary alloc] init]; 505 break; 506 case GPBDataTypeFixed64: 507 case GPBDataTypeUInt64: 508 result = [[GPBUInt32UInt64Dictionary alloc] init]; 509 break; 510 case GPBDataTypeInt64: 511 case GPBDataTypeSFixed64: 512 case GPBDataTypeSInt64: 513 result = [[GPBUInt32Int64Dictionary alloc] init]; 514 break; 515 case GPBDataTypeFloat: 516 result = [[GPBUInt32FloatDictionary alloc] init]; 517 break; 518 case GPBDataTypeDouble: 519 result = [[GPBUInt32DoubleDictionary alloc] init]; 520 break; 521 case GPBDataTypeEnum: 522 result = [[GPBUInt32EnumDictionary alloc] 523 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 524 break; 525 case GPBDataTypeBytes: 526 case GPBDataTypeMessage: 527 case GPBDataTypeString: 528 result = [[GPBUInt32ObjectDictionary alloc] init]; 529 break; 530 case GPBDataTypeGroup: 531 NSCAssert(NO, @"shouldn't happen"); 532 return nil; 533 } 534 break; 535 case GPBDataTypeInt32: 536 case GPBDataTypeSFixed32: 537 case GPBDataTypeSInt32: 538 switch (valueDataType) { 539 case GPBDataTypeBool: 540 result = [[GPBInt32BoolDictionary alloc] init]; 541 break; 542 case GPBDataTypeFixed32: 543 case GPBDataTypeUInt32: 544 result = [[GPBInt32UInt32Dictionary alloc] init]; 545 break; 546 case GPBDataTypeInt32: 547 case GPBDataTypeSFixed32: 548 case GPBDataTypeSInt32: 549 result = [[GPBInt32Int32Dictionary alloc] init]; 550 break; 551 case GPBDataTypeFixed64: 552 case GPBDataTypeUInt64: 553 result = [[GPBInt32UInt64Dictionary alloc] init]; 554 break; 555 case GPBDataTypeInt64: 556 case GPBDataTypeSFixed64: 557 case GPBDataTypeSInt64: 558 result = [[GPBInt32Int64Dictionary alloc] init]; 559 break; 560 case GPBDataTypeFloat: 561 result = [[GPBInt32FloatDictionary alloc] init]; 562 break; 563 case GPBDataTypeDouble: 564 result = [[GPBInt32DoubleDictionary alloc] init]; 565 break; 566 case GPBDataTypeEnum: 567 result = [[GPBInt32EnumDictionary alloc] 568 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 569 break; 570 case GPBDataTypeBytes: 571 case GPBDataTypeMessage: 572 case GPBDataTypeString: 573 result = [[GPBInt32ObjectDictionary alloc] init]; 574 break; 575 case GPBDataTypeGroup: 576 NSCAssert(NO, @"shouldn't happen"); 577 return nil; 578 } 579 break; 580 case GPBDataTypeFixed64: 581 case GPBDataTypeUInt64: 582 switch (valueDataType) { 583 case GPBDataTypeBool: 584 result = [[GPBUInt64BoolDictionary alloc] init]; 585 break; 586 case GPBDataTypeFixed32: 587 case GPBDataTypeUInt32: 588 result = [[GPBUInt64UInt32Dictionary alloc] init]; 589 break; 590 case GPBDataTypeInt32: 591 case GPBDataTypeSFixed32: 592 case GPBDataTypeSInt32: 593 result = [[GPBUInt64Int32Dictionary alloc] init]; 594 break; 595 case GPBDataTypeFixed64: 596 case GPBDataTypeUInt64: 597 result = [[GPBUInt64UInt64Dictionary alloc] init]; 598 break; 599 case GPBDataTypeInt64: 600 case GPBDataTypeSFixed64: 601 case GPBDataTypeSInt64: 602 result = [[GPBUInt64Int64Dictionary alloc] init]; 603 break; 604 case GPBDataTypeFloat: 605 result = [[GPBUInt64FloatDictionary alloc] init]; 606 break; 607 case GPBDataTypeDouble: 608 result = [[GPBUInt64DoubleDictionary alloc] init]; 609 break; 610 case GPBDataTypeEnum: 611 result = [[GPBUInt64EnumDictionary alloc] 612 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 613 break; 614 case GPBDataTypeBytes: 615 case GPBDataTypeMessage: 616 case GPBDataTypeString: 617 result = [[GPBUInt64ObjectDictionary alloc] init]; 618 break; 619 case GPBDataTypeGroup: 620 NSCAssert(NO, @"shouldn't happen"); 621 return nil; 622 } 623 break; 624 case GPBDataTypeInt64: 625 case GPBDataTypeSFixed64: 626 case GPBDataTypeSInt64: 627 switch (valueDataType) { 628 case GPBDataTypeBool: 629 result = [[GPBInt64BoolDictionary alloc] init]; 630 break; 631 case GPBDataTypeFixed32: 632 case GPBDataTypeUInt32: 633 result = [[GPBInt64UInt32Dictionary alloc] init]; 634 break; 635 case GPBDataTypeInt32: 636 case GPBDataTypeSFixed32: 637 case GPBDataTypeSInt32: 638 result = [[GPBInt64Int32Dictionary alloc] init]; 639 break; 640 case GPBDataTypeFixed64: 641 case GPBDataTypeUInt64: 642 result = [[GPBInt64UInt64Dictionary alloc] init]; 643 break; 644 case GPBDataTypeInt64: 645 case GPBDataTypeSFixed64: 646 case GPBDataTypeSInt64: 647 result = [[GPBInt64Int64Dictionary alloc] init]; 648 break; 649 case GPBDataTypeFloat: 650 result = [[GPBInt64FloatDictionary alloc] init]; 651 break; 652 case GPBDataTypeDouble: 653 result = [[GPBInt64DoubleDictionary alloc] init]; 654 break; 655 case GPBDataTypeEnum: 656 result = [[GPBInt64EnumDictionary alloc] 657 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 658 break; 659 case GPBDataTypeBytes: 660 case GPBDataTypeMessage: 661 case GPBDataTypeString: 662 result = [[GPBInt64ObjectDictionary alloc] init]; 663 break; 664 case GPBDataTypeGroup: 665 NSCAssert(NO, @"shouldn't happen"); 666 return nil; 667 } 668 break; 669 case GPBDataTypeString: 670 switch (valueDataType) { 671 case GPBDataTypeBool: 672 result = [[GPBStringBoolDictionary alloc] init]; 673 break; 674 case GPBDataTypeFixed32: 675 case GPBDataTypeUInt32: 676 result = [[GPBStringUInt32Dictionary alloc] init]; 677 break; 678 case GPBDataTypeInt32: 679 case GPBDataTypeSFixed32: 680 case GPBDataTypeSInt32: 681 result = [[GPBStringInt32Dictionary alloc] init]; 682 break; 683 case GPBDataTypeFixed64: 684 case GPBDataTypeUInt64: 685 result = [[GPBStringUInt64Dictionary alloc] init]; 686 break; 687 case GPBDataTypeInt64: 688 case GPBDataTypeSFixed64: 689 case GPBDataTypeSInt64: 690 result = [[GPBStringInt64Dictionary alloc] init]; 691 break; 692 case GPBDataTypeFloat: 693 result = [[GPBStringFloatDictionary alloc] init]; 694 break; 695 case GPBDataTypeDouble: 696 result = [[GPBStringDoubleDictionary alloc] init]; 697 break; 698 case GPBDataTypeEnum: 699 result = [[GPBStringEnumDictionary alloc] 700 initWithValidationFunction:field.enumDescriptor.enumVerifier]; 701 break; 702 case GPBDataTypeBytes: 703 case GPBDataTypeMessage: 704 case GPBDataTypeString: 705 if (autocreator) { 706 result = [[GPBAutocreatedDictionary alloc] init]; 707 } else { 708 result = [[NSMutableDictionary alloc] init]; 709 } 710 break; 711 case GPBDataTypeGroup: 712 NSCAssert(NO, @"shouldn't happen"); 713 return nil; 714 } 715 break; 716 717 case GPBDataTypeFloat: 718 case GPBDataTypeDouble: 719 case GPBDataTypeEnum: 720 case GPBDataTypeBytes: 721 case GPBDataTypeGroup: 722 case GPBDataTypeMessage: 723 NSCAssert(NO, @"shouldn't happen"); 724 return nil; 725 } 726 727 if (autocreator) { 728 if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { 729 GPBAutocreatedDictionary *autoDict = result; 730 autoDict->_autocreator = autocreator; 731 } else { 732 GPBInt32Int32Dictionary *gpbDict = result; 733 gpbDict->_autocreator = autocreator; 734 } 735 } 736 737 return result; 738} 739 740#if !defined(__clang_analyzer__) 741// These functions are blocked from the analyzer because the analyzer sees the 742// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map, 743// so use of the array/map after the call returns is flagged as a use after 744// free. 745// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain 746// count be holding onto the object (it is transferring it), the object is 747// still valid after returning from the call. The other way to avoid this 748// would be to add a -retain/-autorelease, but that would force every 749// repeated/map field parsed into the autorelease pool which is both a memory 750// and performance hit. 751 752static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 753 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 754 if (!array) { 755 // No lock needed, this is called from places expecting to mutate 756 // so no threading protection is needed. 757 array = CreateArrayForField(field, nil); 758 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array); 759 } 760 return array; 761} 762 763// This is like GPBGetObjectIvarWithField(), but for arrays, it should 764// only be used to wire the method into the class. 765static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 766 uint8_t *storage = (uint8_t *)self->messageStorage_; 767 _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 768 id array = atomic_load(typePtr); 769 if (array) { 770 return array; 771 } 772 773 id expected = nil; 774 id autocreated = CreateArrayForField(field, self); 775 if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 776 // Value was set, return it. 777 return autocreated; 778 } 779 780 // Some other thread set it, release the one created and return what got set. 781 if (GPBFieldDataTypeIsObject(field)) { 782 GPBAutocreatedArray *autoArray = autocreated; 783 autoArray->_autocreator = nil; 784 } else { 785 GPBInt32Array *gpbArray = autocreated; 786 gpbArray->_autocreator = nil; 787 } 788 [autocreated release]; 789 return expected; 790} 791 792static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 793 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 794 if (!dict) { 795 // No lock needed, this is called from places expecting to mutate 796 // so no threading protection is needed. 797 dict = CreateMapForField(field, nil); 798 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict); 799 } 800 return dict; 801} 802 803// This is like GPBGetObjectIvarWithField(), but for maps, it should 804// only be used to wire the method into the class. 805static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 806 uint8_t *storage = (uint8_t *)self->messageStorage_; 807 _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 808 id dict = atomic_load(typePtr); 809 if (dict) { 810 return dict; 811 } 812 813 id expected = nil; 814 id autocreated = CreateMapForField(field, self); 815 if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 816 // Value was set, return it. 817 return autocreated; 818 } 819 820 // Some other thread set it, release the one created and return what got set. 821 if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) { 822 GPBAutocreatedDictionary *autoDict = autocreated; 823 autoDict->_autocreator = nil; 824 } else { 825 GPBInt32Int32Dictionary *gpbDict = autocreated; 826 gpbDict->_autocreator = nil; 827 } 828 [autocreated release]; 829 return expected; 830} 831 832#endif // !defined(__clang_analyzer__) 833 834static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension, 835 GPBMessage *messageToGetExtension, 836 GPBCodedInputStream *input, 837 id<GPBExtensionRegistry> extensionRegistry, 838 BOOL isRepeated, GPBMessage *targetMessage) { 839 GPBExtensionDescription *description = extension->description_; 840#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 841 if (GPBDataTypeIsMessage(description->dataType)) { 842 NSCAssert(targetMessage != nil, @"Internal error: must have a target message"); 843 } else { 844 NSCAssert(targetMessage == nil, @"Internal error: should not have a target message"); 845 } 846#endif 847 GPBCodedInputStreamState *state = &input->state_; 848 id nsValue; 849 switch (description->dataType) { 850 case GPBDataTypeBool: { 851 BOOL value = GPBCodedInputStreamReadBool(state); 852 nsValue = [[NSNumber alloc] initWithBool:value]; 853 break; 854 } 855 case GPBDataTypeFixed32: { 856 uint32_t value = GPBCodedInputStreamReadFixed32(state); 857 nsValue = [[NSNumber alloc] initWithUnsignedInt:value]; 858 break; 859 } 860 case GPBDataTypeSFixed32: { 861 int32_t value = GPBCodedInputStreamReadSFixed32(state); 862 nsValue = [[NSNumber alloc] initWithInt:value]; 863 break; 864 } 865 case GPBDataTypeFloat: { 866 float value = GPBCodedInputStreamReadFloat(state); 867 nsValue = [[NSNumber alloc] initWithFloat:value]; 868 break; 869 } 870 case GPBDataTypeFixed64: { 871 uint64_t value = GPBCodedInputStreamReadFixed64(state); 872 nsValue = [[NSNumber alloc] initWithUnsignedLongLong:value]; 873 break; 874 } 875 case GPBDataTypeSFixed64: { 876 int64_t value = GPBCodedInputStreamReadSFixed64(state); 877 nsValue = [[NSNumber alloc] initWithLongLong:value]; 878 break; 879 } 880 case GPBDataTypeDouble: { 881 double value = GPBCodedInputStreamReadDouble(state); 882 nsValue = [[NSNumber alloc] initWithDouble:value]; 883 break; 884 } 885 case GPBDataTypeInt32: { 886 int32_t value = GPBCodedInputStreamReadInt32(state); 887 nsValue = [[NSNumber alloc] initWithInt:value]; 888 break; 889 } 890 case GPBDataTypeInt64: { 891 int64_t value = GPBCodedInputStreamReadInt64(state); 892 nsValue = [[NSNumber alloc] initWithLongLong:value]; 893 break; 894 } 895 case GPBDataTypeSInt32: { 896 int32_t value = GPBCodedInputStreamReadSInt32(state); 897 nsValue = [[NSNumber alloc] initWithInt:value]; 898 break; 899 } 900 case GPBDataTypeSInt64: { 901 int64_t value = GPBCodedInputStreamReadSInt64(state); 902 nsValue = [[NSNumber alloc] initWithLongLong:value]; 903 break; 904 } 905 case GPBDataTypeUInt32: { 906 uint32_t value = GPBCodedInputStreamReadUInt32(state); 907 nsValue = [[NSNumber alloc] initWithUnsignedInt:value]; 908 break; 909 } 910 case GPBDataTypeUInt64: { 911 uint64_t value = GPBCodedInputStreamReadUInt64(state); 912 nsValue = [[NSNumber alloc] initWithUnsignedLongLong:value]; 913 break; 914 } 915 case GPBDataTypeBytes: 916 nsValue = GPBCodedInputStreamReadRetainedBytes(state); 917 break; 918 case GPBDataTypeString: 919 nsValue = GPBCodedInputStreamReadRetainedString(state); 920 break; 921 case GPBDataTypeEnum: { 922 int32_t val = GPBCodedInputStreamReadEnum(&input->state_); 923 GPBEnumDescriptor *enumDescriptor = extension.enumDescriptor; 924 // If run with source generated before the closed enum support, all enums 925 // will be considers not closed, so casing to the enum type for a switch 926 // could cause things to fall off the end of a switch. 927 if (!enumDescriptor.isClosed || enumDescriptor.enumVerifier(val)) { 928 nsValue = [[NSNumber alloc] initWithInt:val]; 929 } else { 930 AddUnknownFieldVarint32(messageToGetExtension, extension->description_->fieldNumber, val); 931 nsValue = nil; 932 } 933 break; 934 } 935 case GPBDataTypeGroup: 936 case GPBDataTypeMessage: { 937 if (description->dataType == GPBDataTypeGroup) { 938 [input readGroup:description->fieldNumber 939 message:targetMessage 940 extensionRegistry:extensionRegistry]; 941 } else { 942// description->dataType == GPBDataTypeMessage 943#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 944 NSCAssert(!GPBExtensionIsWireFormat(description), 945 @"Internal error: got a MessageSet extension when not expected."); 946#endif 947 [input readMessage:targetMessage extensionRegistry:extensionRegistry]; 948 } 949 // Nothing to add below since the caller provided the message (and added it). 950 nsValue = nil; 951 break; 952 } 953 } // switch 954 955 if (nsValue) { 956 if (isRepeated) { 957 [messageToGetExtension addExtension:extension value:nsValue]; 958 } else { 959 [messageToGetExtension setExtension:extension value:nsValue]; 960 } 961 [nsValue release]; 962 } 963} 964 965static void ExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, BOOL isPackedOnStream, 966 GPBCodedInputStream *input, 967 id<GPBExtensionRegistry> extensionRegistry, 968 GPBMessage *message) { 969 GPBExtensionDescription *description = extension->description_; 970 GPBCodedInputStreamState *state = &input->state_; 971 if (isPackedOnStream) { 972#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 973 NSCAssert(GPBExtensionIsRepeated(description), @"How was it packed if it isn't repeated?"); 974#endif 975 int32_t length = GPBCodedInputStreamReadInt32(state); 976 size_t limit = GPBCodedInputStreamPushLimit(state, length); 977 while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { 978 DecodeSingleValueFromInputStream(extension, message, input, extensionRegistry, 979 /*isRepeated=*/YES, nil); 980 } 981 GPBCodedInputStreamPopLimit(state, limit); 982 } else { 983 BOOL isRepeated = GPBExtensionIsRepeated(description); 984 GPBMessage *targetMessage = nil; 985 if (GPBDataTypeIsMessage(description->dataType)) { 986 // For messages/groups create the targetMessage out here and add it to the objects graph in 987 // advance, that way if DecodeSingleValueFromInputStream() throw for a parsing issue, the 988 // object won't be leaked. 989 if (isRepeated) { 990 GPBDescriptor *descriptor = [extension.msgClass descriptor]; 991 targetMessage = [[descriptor.messageClass alloc] init]; 992 [message addExtension:extension value:targetMessage]; 993 [targetMessage release]; 994 } else { 995 targetMessage = [message getExistingExtension:extension]; 996 if (!targetMessage) { 997 GPBDescriptor *descriptor = [extension.msgClass descriptor]; 998 targetMessage = [[descriptor.messageClass alloc] init]; 999 [message setExtension:extension value:targetMessage]; 1000 [targetMessage release]; 1001 } 1002 } 1003 } 1004 DecodeSingleValueFromInputStream(extension, message, input, extensionRegistry, isRepeated, 1005 targetMessage); 1006 } 1007} 1008 1009static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator, 1010 GPBFieldDescriptor *field) { 1011 GPBMessage *message = [[msgClass alloc] init]; 1012 message->autocreator_ = autocreator; 1013 message->autocreatorField_ = [field retain]; 1014 return message; 1015} 1016 1017static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator, 1018 GPBExtensionDescriptor *extension) 1019 __attribute__((ns_returns_retained)); 1020 1021static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator, 1022 GPBExtensionDescriptor *extension) { 1023 GPBMessage *message = [[msgClass alloc] init]; 1024 message->autocreator_ = autocreator; 1025 message->autocreatorExtension_ = [extension retain]; 1026 return message; 1027} 1028 1029BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) { 1030 return (message->autocreator_ == parent); 1031} 1032 1033void GPBBecomeVisibleToAutocreator(GPBMessage *self) { 1034 // Message objects that are implicitly created by accessing a message field 1035 // are initially not visible via the hasX selector. This method makes them 1036 // visible. 1037 if (self->autocreator_) { 1038 // This will recursively make all parent messages visible until it reaches a 1039 // super-creator that's visible. 1040 if (self->autocreatorField_) { 1041 GPBSetObjectIvarWithFieldPrivate(self->autocreator_, self->autocreatorField_, self); 1042 } else { 1043 [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; 1044 } 1045 } 1046} 1047 1048void GPBAutocreatedArrayModified(GPBMessage *self, id array) { 1049 // When one of our autocreated arrays adds elements, make it visible. 1050 GPBDescriptor *descriptor = [[self class] descriptor]; 1051 for (GPBFieldDescriptor *field in descriptor->fields_) { 1052 if (field.fieldType == GPBFieldTypeRepeated) { 1053 id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1054 if (curArray == array) { 1055 if (GPBFieldDataTypeIsObject(field)) { 1056 GPBAutocreatedArray *autoArray = array; 1057 autoArray->_autocreator = nil; 1058 } else { 1059 GPBInt32Array *gpbArray = array; 1060 gpbArray->_autocreator = nil; 1061 } 1062 GPBBecomeVisibleToAutocreator(self); 1063 return; 1064 } 1065 } 1066 } 1067 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); 1068} 1069 1070void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { 1071 // When one of our autocreated dicts adds elements, make it visible. 1072 GPBDescriptor *descriptor = [[self class] descriptor]; 1073 for (GPBFieldDescriptor *field in descriptor->fields_) { 1074 if (field.fieldType == GPBFieldTypeMap) { 1075 id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1076 if (curDict == dictionary) { 1077 if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) { 1078 GPBAutocreatedDictionary *autoDict = dictionary; 1079 autoDict->_autocreator = nil; 1080 } else { 1081 GPBInt32Int32Dictionary *gpbDict = dictionary; 1082 gpbDict->_autocreator = nil; 1083 } 1084 GPBBecomeVisibleToAutocreator(self); 1085 return; 1086 } 1087 } 1088 } 1089 NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); 1090} 1091 1092void GPBClearMessageAutocreator(GPBMessage *self) { 1093 if ((self == nil) || !self->autocreator_) { 1094 return; 1095 } 1096 1097#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 1098 // Either the autocreator must have its "has" flag set to YES, or it must be 1099 // NO and not equal to ourselves. 1100 BOOL autocreatorHas = 1101 (self->autocreatorField_ ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_) 1102 : [self->autocreator_ hasExtension:self->autocreatorExtension_]); 1103 GPBMessage *autocreatorFieldValue = 1104 (self->autocreatorField_ 1105 ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, self->autocreatorField_) 1106 : [self->autocreator_->autocreatedExtensionMap_ 1107 objectForKey:self->autocreatorExtension_]); 1108 NSCAssert(autocreatorHas || autocreatorFieldValue != self, 1109 @"Cannot clear autocreator because it still refers to self, self: %@.", self); 1110 1111#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) 1112 1113 self->autocreator_ = nil; 1114 [self->autocreatorField_ release]; 1115 self->autocreatorField_ = nil; 1116 [self->autocreatorExtension_ release]; 1117 self->autocreatorExtension_ = nil; 1118} 1119 1120#pragma clang diagnostic push 1121#pragma clang diagnostic ignored "-Wdeprecated-declarations" 1122GPB_NOINLINE 1123static void MergeUnknownFieldDataIntoFieldSet(GPBMessage *self, NSData *data, 1124 GPBUnknownFieldSet *targetSet) { 1125 GPBUnknownFieldSet *unknownFields = targetSet ? targetSet : self->unknownFields_; 1126 1127#if defined(DEBUG) && DEBUG 1128 NSCAssert(unknownFields != nil, @"Internal error: unknown fields not initialized."); 1129#endif 1130 1131 BOOL isMessageSet = self.descriptor.isWireFormat; 1132 GPBUnknownFieldSet *decodeInto = isMessageSet ? [[GPBUnknownFieldSet alloc] init] : unknownFields; 1133 1134 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 1135 @try { 1136 [decodeInto mergeFromCodedInputStream:input]; 1137 } @catch (NSException *exception) { 1138#if defined(DEBUG) && DEBUG 1139 NSLog(@"%@: Internal exception while parsing the unknown fields into a Set: %@", [self class], 1140 exception); 1141#endif 1142 } 1143 [input release]; 1144 1145 if (isMessageSet) { 1146 // Need to transform the groups back into how Message feeds the data into a MessageSet when 1147 // doing a full MessageSet based decode. 1148 GPBUnknownField *groupField = [decodeInto getField:GPBWireFormatMessageSetItem]; 1149 for (GPBUnknownFieldSet *group in groupField.groupList) { 1150 GPBUnknownField *typeIdField = [group getField:GPBWireFormatMessageSetTypeId]; 1151 GPBUnknownField *messageField = [group getField:GPBWireFormatMessageSetMessage]; 1152 if (typeIdField.varintList.count != 1 || messageField.lengthDelimitedList.count != 1) { 1153#if defined(DEBUG) && DEBUG 1154 NSCAssert(NO, @"Internal error: MessageSet group missing typeId or message."); 1155#endif 1156 continue; 1157 } 1158 int32_t fieldNumber = (int32_t)[typeIdField.varintList valueAtIndex:0]; 1159 GPBUnknownField *messageSetField = [[GPBUnknownField alloc] initWithNumber:fieldNumber]; 1160 [messageSetField addLengthDelimited:messageField.lengthDelimitedList[0]]; 1161 [unknownFields addField:messageSetField]; 1162 [messageSetField release]; 1163 } 1164 [decodeInto release]; 1165 } 1166} 1167#pragma clang diagnostic pop 1168 1169@implementation GPBMessage 1170 1171+ (void)initialize { 1172 Class pbMessageClass = [GPBMessage class]; 1173 if ([self class] == pbMessageClass) { 1174 // This is here to start up the "base" class descriptor. 1175 [self descriptor]; 1176 // Message shares extension method resolving with GPBRootObject so insure 1177 // it is started up at the same time. 1178 (void)[GPBRootObject class]; 1179 } else if ([self superclass] == pbMessageClass) { 1180 // This is here to start up all the "message" subclasses. Just needs to be 1181 // done for the messages, not any of the subclasses. 1182 // This must be done in initialize to enforce thread safety of start up of 1183 // the protocol buffer library. 1184 // Note: The generated code for -descriptor calls 1185 // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject 1186 // subclass for the file. That call chain is what ensures that *Root class 1187 // is started up to support extension resolution off the message class 1188 // (+resolveClassMethod: below) in a thread safe manner. 1189 [self descriptor]; 1190 } 1191} 1192 1193+ (instancetype)allocWithZone:(NSZone *)zone { 1194 // Override alloc to allocate our classes with the additional storage 1195 // required for the instance variables. 1196 GPBDescriptor *descriptor = [self descriptor]; 1197 return NSAllocateObject(self, descriptor->storageSize_, zone); 1198} 1199 1200+ (instancetype)alloc { 1201 return [self allocWithZone:nil]; 1202} 1203 1204+ (GPBDescriptor *)descriptor { 1205 // This is thread safe because it is called from +initialize. 1206 static GPBDescriptor *descriptor = NULL; 1207 static GPBFileDescription fileDescription = { 1208 .package = "internal", .prefix = "", .syntax = GPBFileSyntaxProto2}; 1209 if (!descriptor) { 1210 descriptor = [GPBDescriptor 1211 allocDescriptorForClass:[GPBMessage class] 1212 messageName:@"GPBMessage" 1213 fileDescription:&fileDescription 1214 fields:NULL 1215 fieldCount:0 1216 storageSize:0 1217 flags:(GPBDescriptorInitializationFlag_UsesClassRefs | 1218 GPBDescriptorInitializationFlag_Proto3OptionalKnown | 1219 GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)]; 1220 } 1221 return descriptor; 1222} 1223 1224+ (instancetype)message { 1225 return [[[self alloc] init] autorelease]; 1226} 1227 1228- (instancetype)init { 1229 if ((self = [super init])) { 1230 messageStorage_ = 1231 (GPBMessage_StoragePtr)(((uint8_t *)self) + class_getInstanceSize([self class])); 1232 readOnlyLock_ = OS_UNFAIR_LOCK_INIT; 1233 } 1234 1235 return self; 1236} 1237 1238- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { 1239 return [self initWithData:data extensionRegistry:nil error:errorPtr]; 1240} 1241 1242- (instancetype)initWithData:(NSData *)data 1243 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 1244 error:(NSError **)errorPtr { 1245 if ((self = [self init])) { 1246 if (![self mergeFromData:data extensionRegistry:extensionRegistry error:errorPtr]) { 1247 [self release]; 1248 self = nil; 1249#if defined(DEBUG) && DEBUG 1250 } else if (!self.initialized) { 1251 [self release]; 1252 self = nil; 1253 if (errorPtr) { 1254 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); 1255 } 1256#endif 1257 } 1258 } 1259 return self; 1260} 1261 1262- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input 1263 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 1264 error:(NSError **)errorPtr { 1265 if ((self = [self init])) { 1266 @try { 1267 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; 1268 if (errorPtr) { 1269 *errorPtr = nil; 1270 } 1271 } @catch (NSException *exception) { 1272 [self release]; 1273 self = nil; 1274 if (errorPtr) { 1275 *errorPtr = ErrorFromException(exception); 1276 } 1277 } 1278#if defined(DEBUG) && DEBUG 1279 if (self && !self.initialized) { 1280 [self release]; 1281 self = nil; 1282 if (errorPtr) { 1283 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); 1284 } 1285 } 1286#endif 1287 } 1288 return self; 1289} 1290 1291- (void)dealloc { 1292 [self internalClear:NO]; 1293 NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); 1294 [super dealloc]; 1295} 1296 1297- (void)copyFieldsInto:(GPBMessage *)message 1298 zone:(NSZone *)zone 1299 descriptor:(GPBDescriptor *)descriptor { 1300 // Copy all the storage... 1301 memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); 1302 1303 // Loop over the fields doing fixup... 1304 for (GPBFieldDescriptor *field in descriptor->fields_) { 1305 if (GPBFieldIsMapOrArray(field)) { 1306 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1307 if (value) { 1308 // We need to copy the array/map, but the catch is for message fields, 1309 // we also need to ensure all the messages as those need copying also. 1310 id newValue; 1311 if (GPBFieldDataTypeIsMessage(field)) { 1312 if (field.fieldType == GPBFieldTypeRepeated) { 1313 NSArray *existingArray = (NSArray *)value; 1314 NSMutableArray *newArray = 1315 [[NSMutableArray alloc] initWithCapacity:existingArray.count]; 1316 newValue = newArray; 1317 for (GPBMessage *msg in existingArray) { 1318 GPBMessage *copiedMsg = [msg copyWithZone:zone]; 1319 [newArray addObject:copiedMsg]; 1320 [copiedMsg release]; 1321 } 1322 } else { 1323 if (field.mapKeyDataType == GPBDataTypeString) { 1324 // Map is an NSDictionary. 1325 NSDictionary *existingDict = value; 1326 NSMutableDictionary *newDict = 1327 [[NSMutableDictionary alloc] initWithCapacity:existingDict.count]; 1328 newValue = newDict; 1329 [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, GPBMessage *msg, 1330 __unused BOOL *stop) { 1331 GPBMessage *copiedMsg = [msg copyWithZone:zone]; 1332 [newDict setObject:copiedMsg forKey:key]; 1333 [copiedMsg release]; 1334 }]; 1335 } else { 1336 // Is one of the GPB*ObjectDictionary classes. Type doesn't 1337 // matter, just need one to invoke the selector. 1338 GPBInt32ObjectDictionary *existingDict = value; 1339 newValue = [existingDict deepCopyWithZone:zone]; 1340 } 1341 } 1342 } else { 1343 // Not messages (but is a map/array)... 1344 if (field.fieldType == GPBFieldTypeRepeated) { 1345 if (GPBFieldDataTypeIsObject(field)) { 1346 // NSArray 1347 newValue = [value mutableCopyWithZone:zone]; 1348 } else { 1349 // GPB*Array 1350 newValue = [value copyWithZone:zone]; 1351 } 1352 } else { 1353 if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) { 1354 // NSDictionary 1355 newValue = [value mutableCopyWithZone:zone]; 1356 } else { 1357 // Is one of the GPB*Dictionary classes. Type doesn't matter, 1358 // just need one to invoke the selector. 1359 GPBInt32Int32Dictionary *existingDict = value; 1360 newValue = [existingDict copyWithZone:zone]; 1361 } 1362 } 1363 } 1364 // We retain here because the memcpy picked up the pointer value and 1365 // the next call to SetRetainedObject... will release the current value. 1366 [value retain]; 1367 GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1368 } 1369 } else if (GPBFieldDataTypeIsMessage(field)) { 1370 // For object types, if we have a value, copy it. If we don't, 1371 // zero it to remove the pointer to something that was autocreated 1372 // (and the ptr just got memcpyed). 1373 if (GPBGetHasIvarField(self, field)) { 1374 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1375 GPBMessage *newValue = [value copyWithZone:zone]; 1376 // We retain here because the memcpy picked up the pointer value and 1377 // the next call to SetRetainedObject... will release the current value. 1378 [value retain]; 1379 GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1380 } else { 1381 uint8_t *storage = (uint8_t *)message->messageStorage_; 1382 id *typePtr = (id *)&storage[field->description_->offset]; 1383 *typePtr = NULL; 1384 } 1385 } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) { 1386 // A set string/data value (message picked off above), copy it. 1387 id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1388 id newValue = [value copyWithZone:zone]; 1389 // We retain here because the memcpy picked up the pointer value and 1390 // the next call to SetRetainedObject... will release the current value. 1391 [value retain]; 1392 GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1393 } else { 1394 // memcpy took care of the rest of the primitive fields if they were set. 1395 } 1396 } // for (field in descriptor->fields_) 1397} 1398 1399- (id)copyWithZone:(NSZone *)zone { 1400 GPBDescriptor *descriptor = [self descriptor]; 1401 GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; 1402 1403 [self copyFieldsInto:result zone:zone descriptor:descriptor]; 1404 1405 @synchronized(self) { 1406 result->unknownFields_ = [unknownFields_ copyWithZone:zone]; 1407 result->unknownFieldData_ = [unknownFieldData_ mutableCopyWithZone:zone]; 1408 } 1409 1410 result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); 1411 return result; 1412} 1413 1414- (void)clear { 1415 [self internalClear:YES]; 1416} 1417 1418- (void)internalClear:(BOOL)zeroStorage { 1419 GPBDescriptor *descriptor = [self descriptor]; 1420 for (GPBFieldDescriptor *field in descriptor->fields_) { 1421 if (GPBFieldIsMapOrArray(field)) { 1422 id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1423 if (arrayOrMap) { 1424 if (field.fieldType == GPBFieldTypeRepeated) { 1425 if (GPBFieldDataTypeIsObject(field)) { 1426 if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) { 1427 GPBAutocreatedArray *autoArray = arrayOrMap; 1428 if (autoArray->_autocreator == self) { 1429 autoArray->_autocreator = nil; 1430 } 1431 } 1432 } else { 1433 // Type doesn't matter, it is a GPB*Array. 1434 GPBInt32Array *gpbArray = arrayOrMap; 1435 if (gpbArray->_autocreator == self) { 1436 gpbArray->_autocreator = nil; 1437 } 1438 } 1439 } else { 1440 if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) { 1441 if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) { 1442 GPBAutocreatedDictionary *autoDict = arrayOrMap; 1443 if (autoDict->_autocreator == self) { 1444 autoDict->_autocreator = nil; 1445 } 1446 } 1447 } else { 1448 // Type doesn't matter, it is a GPB*Dictionary. 1449 GPBInt32Int32Dictionary *gpbDict = arrayOrMap; 1450 if (gpbDict->_autocreator == self) { 1451 gpbDict->_autocreator = nil; 1452 } 1453 } 1454 } 1455 [arrayOrMap release]; 1456 } 1457 } else if (GPBFieldDataTypeIsMessage(field)) { 1458 GPBClearAutocreatedMessageIvarWithField(self, field); 1459 GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1460 [value release]; 1461 } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) { 1462 id value = GPBGetObjectIvarWithField(self, field); 1463 [value release]; 1464 } 1465 } 1466 1467 // GPBClearMessageAutocreator() expects that its caller has already been 1468 // removed from autocreatedExtensionMap_ so we set to nil first. 1469 NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues]; 1470 [autocreatedExtensionMap_ release]; 1471 autocreatedExtensionMap_ = nil; 1472 1473 // Since we're clearing all of our extensions, make sure that we clear the 1474 // autocreator on any that we've created so they no longer refer to us. 1475 for (GPBMessage *value in autocreatedValues) { 1476 NSCAssert(GPBWasMessageAutocreatedBy(value, self), 1477 @"Autocreated extension does not refer back to self."); 1478 GPBClearMessageAutocreator(value); 1479 } 1480 1481 [extensionMap_ release]; 1482 extensionMap_ = nil; 1483 [unknownFieldData_ release]; 1484 unknownFieldData_ = nil; 1485 [unknownFields_ release]; 1486 unknownFields_ = nil; 1487 1488 // Note that clearing does not affect autocreator_. If we are being cleared 1489 // because of a dealloc, then autocreator_ should be nil anyway. If we are 1490 // being cleared because someone explicitly clears us, we don't want to 1491 // sever our relationship with our autocreator. 1492 1493 if (zeroStorage) { 1494 memset(messageStorage_, 0, descriptor->storageSize_); 1495 } 1496} 1497 1498- (void)clearUnknownFields { 1499 [unknownFieldData_ release]; 1500 unknownFieldData_ = nil; 1501#pragma clang diagnostic push 1502#pragma clang diagnostic ignored "-Wdeprecated-declarations" 1503 [unknownFields_ release]; 1504 unknownFields_ = nil; 1505#pragma clang diagnostic pop 1506 GPBBecomeVisibleToAutocreator(self); 1507} 1508 1509- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields 1510 extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry 1511 error:(NSError **)errorPtr { 1512 return [self mergeFromData:[unknownFields serializeAsData] 1513 extensionRegistry:extensionRegistry 1514 error:errorPtr]; 1515} 1516 1517- (BOOL)isInitialized { 1518 GPBDescriptor *descriptor = [self descriptor]; 1519 for (GPBFieldDescriptor *field in descriptor->fields_) { 1520 if (field.isRequired) { 1521 if (!GPBGetHasIvarField(self, field)) { 1522 return NO; 1523 } 1524 } 1525 if (GPBFieldDataTypeIsMessage(field)) { 1526 GPBFieldType fieldType = field.fieldType; 1527 if (fieldType == GPBFieldTypeSingle) { 1528 if (field.isRequired) { 1529 GPBMessage *message = GPBGetMessageMessageField(self, field); 1530 if (!message.initialized) { 1531 return NO; 1532 } 1533 } else { 1534 NSAssert(field.isOptional, @"%@: Single message field %@ not required or optional?", 1535 [self class], field.name); 1536 if (GPBGetHasIvarField(self, field)) { 1537 GPBMessage *message = GPBGetMessageMessageField(self, field); 1538 if (!message.initialized) { 1539 return NO; 1540 } 1541 } 1542 } 1543 } else if (fieldType == GPBFieldTypeRepeated) { 1544 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1545 for (GPBMessage *message in array) { 1546 if (!message.initialized) { 1547 return NO; 1548 } 1549 } 1550 } else { // fieldType == GPBFieldTypeMap 1551 if (field.mapKeyDataType == GPBDataTypeString) { 1552 NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1553 if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { 1554 return NO; 1555 } 1556 } else { 1557 // Real type is GPB*ObjectDictionary, exact type doesn't matter. 1558 GPBInt32ObjectDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1559 if (map && ![map isInitialized]) { 1560 return NO; 1561 } 1562 } 1563 } 1564 } 1565 } 1566 1567 __block BOOL result = YES; 1568 [extensionMap_ 1569 enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, id obj, BOOL *stop) { 1570 if (GPBExtensionIsMessage(extension)) { 1571 if (extension.isRepeated) { 1572 for (GPBMessage *msg in obj) { 1573 if (!msg.initialized) { 1574 result = NO; 1575 *stop = YES; 1576 break; 1577 } 1578 } 1579 } else { 1580 GPBMessage *asMsg = obj; 1581 if (!asMsg.initialized) { 1582 result = NO; 1583 *stop = YES; 1584 } 1585 } 1586 } 1587 }]; 1588 return result; 1589} 1590 1591- (GPBDescriptor *)descriptor { 1592 return [[self class] descriptor]; 1593} 1594 1595- (NSData *)data { 1596#if defined(DEBUG) && DEBUG 1597 if (!self.initialized) { 1598 return nil; 1599 } 1600#endif 1601 size_t expectedSize = [self serializedSize]; 1602 if (expectedSize > kMaximumMessageSize) { 1603 return nil; 1604 } 1605 NSMutableData *data = [NSMutableData dataWithLength:expectedSize]; 1606 GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; 1607 @try { 1608 [self writeToCodedOutputStream:stream]; 1609 [stream flush]; 1610 } @catch (NSException *exception) { 1611 // This really shouldn't happen. Normally, this could mean there was a bug in the library and it 1612 // failed to match between computing the size and writing out the bytes. However, the more 1613 // common cause is while one thread was writing out the data, some other thread had a reference 1614 // to this message or a message used as a nested field, and that other thread mutated that 1615 // message, causing the pre computed serializedSize to no longer match the final size after 1616 // serialization. It is not safe to mutate a message while accessing it from another thread. 1617#if defined(DEBUG) && DEBUG 1618 NSLog(@"%@: Internal exception while building message data: %@", [self class], exception); 1619#endif 1620 data = nil; 1621 } 1622#if defined(DEBUG) && DEBUG 1623 NSAssert(!data || [stream bytesWritten] == expectedSize, @"Internal error within the library"); 1624#endif 1625 [stream release]; 1626 return data; 1627} 1628 1629- (NSData *)delimitedData { 1630 size_t serializedSize = [self serializedSize]; 1631 size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize); 1632 NSMutableData *data = [NSMutableData dataWithLength:(serializedSize + varintSize)]; 1633 GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; 1634 @try { 1635 [self writeDelimitedToCodedOutputStream:stream]; 1636 [stream flush]; 1637 } @catch (NSException *exception) { 1638 // This really shouldn't happen. Normally, this could mean there was a bug in the library and it 1639 // failed to match between computing the size and writing out the bytes. However, the more 1640 // common cause is while one thread was writing out the data, some other thread had a reference 1641 // to this message or a message used as a nested field, and that other thread mutated that 1642 // message, causing the pre computed serializedSize to no longer match the final size after 1643 // serialization. It is not safe to mutate a message while accessing it from another thread. 1644#if defined(DEBUG) && DEBUG 1645 NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class], 1646 exception); 1647#endif 1648 // If it happens, return an empty data. 1649 [stream release]; 1650 return [NSData data]; 1651 } 1652 [stream release]; 1653 return data; 1654} 1655 1656- (void)writeToOutputStream:(NSOutputStream *)output { 1657 GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithOutputStream:output]; 1658 @try { 1659 [self writeToCodedOutputStream:stream]; 1660 [stream flush]; 1661 size_t bytesWritten = [stream bytesWritten]; 1662 if (bytesWritten > kMaximumMessageSize) { 1663 [NSException raise:GPBMessageExceptionMessageTooLarge 1664 format:@"Message would have been %zu bytes", bytesWritten]; 1665 } 1666 } @finally { 1667 [stream release]; 1668 } 1669} 1670 1671- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { 1672 GPBDescriptor *descriptor = [self descriptor]; 1673 NSArray *fieldsArray = descriptor->fields_; 1674 NSUInteger fieldCount = fieldsArray.count; 1675 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; 1676 NSUInteger extensionRangesCount = descriptor.extensionRangesCount; 1677 NSArray *sortedExtensions = 1678 [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; 1679 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { 1680 if (i == fieldCount) { 1681 [self writeExtensionsToCodedOutputStream:output 1682 range:extensionRanges[j++] 1683 sortedExtensions:sortedExtensions]; 1684 } else if (j == extensionRangesCount || 1685 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { 1686 [self writeField:fieldsArray[i++] toCodedOutputStream:output]; 1687 } else { 1688 [self writeExtensionsToCodedOutputStream:output 1689 range:extensionRanges[j++] 1690 sortedExtensions:sortedExtensions]; 1691 } 1692 } 1693 @synchronized(self) { 1694 if (unknownFieldData_) { 1695#if defined(DEBUG) && DEBUG 1696 NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set"); 1697#endif 1698 [output writeRawData:unknownFieldData_]; 1699 } else { 1700 if (descriptor.isWireFormat) { 1701 [unknownFields_ writeAsMessageSetTo:output]; 1702 } else { 1703 [unknownFields_ writeToCodedOutputStream:output]; 1704 } 1705 } 1706 } // @synchronized(self) 1707} 1708 1709- (void)writeDelimitedToOutputStream:(NSOutputStream *)output { 1710 GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output]; 1711 @try { 1712 [self writeDelimitedToCodedOutputStream:codedOutput]; 1713 [codedOutput flush]; 1714 } @finally { 1715 [codedOutput release]; 1716 } 1717} 1718 1719- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output { 1720 size_t expectedSize = [self serializedSize]; 1721 if (expectedSize > kMaximumMessageSize) { 1722 [NSException raise:GPBMessageExceptionMessageTooLarge 1723 format:@"Message would have been %zu bytes", expectedSize]; 1724 } 1725 [output writeRawVarintSizeTAs32:expectedSize]; 1726#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 1727 size_t initialSize = [output bytesWritten]; 1728#endif 1729 [self writeToCodedOutputStream:output]; 1730#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 1731 NSAssert(([output bytesWritten] - initialSize) == expectedSize, 1732 @"Internal error within the library"); 1733#endif 1734} 1735 1736- (void)writeField:(GPBFieldDescriptor *)field toCodedOutputStream:(GPBCodedOutputStream *)output { 1737 GPBFieldType fieldType = field.fieldType; 1738 if (fieldType == GPBFieldTypeSingle) { 1739 BOOL has = GPBGetHasIvarField(self, field); 1740 if (!has) { 1741 return; 1742 } 1743 } 1744 uint32_t fieldNumber = GPBFieldNumber(field); 1745 1746 switch (GPBGetFieldDataType(field)) { 1747 // clang-format off 1748 1749//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) 1750//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) 1751//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) 1752//% case GPBDataType##TYPE: 1753//% if (fieldType == GPBFieldTypeRepeated) { 1754//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1755//% GPB##ARRAY_TYPE##Array *array = 1756//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1757//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; 1758//% } else if (fieldType == GPBFieldTypeSingle) { 1759//% [output write##TYPE:fieldNumber 1760//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; 1761//% } else { // fieldType == GPBFieldTypeMap 1762//% // Exact type here doesn't matter. 1763//% GPBInt32##ARRAY_TYPE##Dictionary *dict = 1764//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1765//% [dict writeToCodedOutputStream:output asField:field]; 1766//% } 1767//% break; 1768//% 1769//%PDDM-DEFINE FIELD_CASE2(TYPE) 1770//% case GPBDataType##TYPE: 1771//% if (fieldType == GPBFieldTypeRepeated) { 1772//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1773//% [output write##TYPE##Array:fieldNumber values:array]; 1774//% } else if (fieldType == GPBFieldTypeSingle) { 1775//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1776//% // again. 1777//% [output write##TYPE:fieldNumber 1778//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1779//% } else { // fieldType == GPBFieldTypeMap 1780//% // Exact type here doesn't matter. 1781//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1782//% GPBDataType mapKeyDataType = field.mapKeyDataType; 1783//% if (mapKeyDataType == GPBDataTypeString) { 1784//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1785//% } else { 1786//% [dict writeToCodedOutputStream:output asField:field]; 1787//% } 1788//% } 1789//% break; 1790//% 1791//%PDDM-EXPAND FIELD_CASE(Bool, Bool) 1792// This block of code is generated, do not edit it directly. 1793 1794 case GPBDataTypeBool: 1795 if (fieldType == GPBFieldTypeRepeated) { 1796 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1797 GPBBoolArray *array = 1798 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1799 [output writeBoolArray:fieldNumber values:array tag:tag]; 1800 } else if (fieldType == GPBFieldTypeSingle) { 1801 [output writeBool:fieldNumber 1802 value:GPBGetMessageBoolField(self, field)]; 1803 } else { // fieldType == GPBFieldTypeMap 1804 // Exact type here doesn't matter. 1805 GPBInt32BoolDictionary *dict = 1806 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1807 [dict writeToCodedOutputStream:output asField:field]; 1808 } 1809 break; 1810 1811//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) 1812// This block of code is generated, do not edit it directly. 1813 1814 case GPBDataTypeFixed32: 1815 if (fieldType == GPBFieldTypeRepeated) { 1816 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1817 GPBUInt32Array *array = 1818 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1819 [output writeFixed32Array:fieldNumber values:array tag:tag]; 1820 } else if (fieldType == GPBFieldTypeSingle) { 1821 [output writeFixed32:fieldNumber 1822 value:GPBGetMessageUInt32Field(self, field)]; 1823 } else { // fieldType == GPBFieldTypeMap 1824 // Exact type here doesn't matter. 1825 GPBInt32UInt32Dictionary *dict = 1826 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1827 [dict writeToCodedOutputStream:output asField:field]; 1828 } 1829 break; 1830 1831//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) 1832// This block of code is generated, do not edit it directly. 1833 1834 case GPBDataTypeSFixed32: 1835 if (fieldType == GPBFieldTypeRepeated) { 1836 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1837 GPBInt32Array *array = 1838 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1839 [output writeSFixed32Array:fieldNumber values:array tag:tag]; 1840 } else if (fieldType == GPBFieldTypeSingle) { 1841 [output writeSFixed32:fieldNumber 1842 value:GPBGetMessageInt32Field(self, field)]; 1843 } else { // fieldType == GPBFieldTypeMap 1844 // Exact type here doesn't matter. 1845 GPBInt32Int32Dictionary *dict = 1846 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1847 [dict writeToCodedOutputStream:output asField:field]; 1848 } 1849 break; 1850 1851//%PDDM-EXPAND FIELD_CASE(Float, Float) 1852// This block of code is generated, do not edit it directly. 1853 1854 case GPBDataTypeFloat: 1855 if (fieldType == GPBFieldTypeRepeated) { 1856 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1857 GPBFloatArray *array = 1858 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1859 [output writeFloatArray:fieldNumber values:array tag:tag]; 1860 } else if (fieldType == GPBFieldTypeSingle) { 1861 [output writeFloat:fieldNumber 1862 value:GPBGetMessageFloatField(self, field)]; 1863 } else { // fieldType == GPBFieldTypeMap 1864 // Exact type here doesn't matter. 1865 GPBInt32FloatDictionary *dict = 1866 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1867 [dict writeToCodedOutputStream:output asField:field]; 1868 } 1869 break; 1870 1871//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) 1872// This block of code is generated, do not edit it directly. 1873 1874 case GPBDataTypeFixed64: 1875 if (fieldType == GPBFieldTypeRepeated) { 1876 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1877 GPBUInt64Array *array = 1878 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1879 [output writeFixed64Array:fieldNumber values:array tag:tag]; 1880 } else if (fieldType == GPBFieldTypeSingle) { 1881 [output writeFixed64:fieldNumber 1882 value:GPBGetMessageUInt64Field(self, field)]; 1883 } else { // fieldType == GPBFieldTypeMap 1884 // Exact type here doesn't matter. 1885 GPBInt32UInt64Dictionary *dict = 1886 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1887 [dict writeToCodedOutputStream:output asField:field]; 1888 } 1889 break; 1890 1891//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) 1892// This block of code is generated, do not edit it directly. 1893 1894 case GPBDataTypeSFixed64: 1895 if (fieldType == GPBFieldTypeRepeated) { 1896 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1897 GPBInt64Array *array = 1898 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1899 [output writeSFixed64Array:fieldNumber values:array tag:tag]; 1900 } else if (fieldType == GPBFieldTypeSingle) { 1901 [output writeSFixed64:fieldNumber 1902 value:GPBGetMessageInt64Field(self, field)]; 1903 } else { // fieldType == GPBFieldTypeMap 1904 // Exact type here doesn't matter. 1905 GPBInt32Int64Dictionary *dict = 1906 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1907 [dict writeToCodedOutputStream:output asField:field]; 1908 } 1909 break; 1910 1911//%PDDM-EXPAND FIELD_CASE(Double, Double) 1912// This block of code is generated, do not edit it directly. 1913 1914 case GPBDataTypeDouble: 1915 if (fieldType == GPBFieldTypeRepeated) { 1916 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1917 GPBDoubleArray *array = 1918 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1919 [output writeDoubleArray:fieldNumber values:array tag:tag]; 1920 } else if (fieldType == GPBFieldTypeSingle) { 1921 [output writeDouble:fieldNumber 1922 value:GPBGetMessageDoubleField(self, field)]; 1923 } else { // fieldType == GPBFieldTypeMap 1924 // Exact type here doesn't matter. 1925 GPBInt32DoubleDictionary *dict = 1926 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1927 [dict writeToCodedOutputStream:output asField:field]; 1928 } 1929 break; 1930 1931//%PDDM-EXPAND FIELD_CASE(Int32, Int32) 1932// This block of code is generated, do not edit it directly. 1933 1934 case GPBDataTypeInt32: 1935 if (fieldType == GPBFieldTypeRepeated) { 1936 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1937 GPBInt32Array *array = 1938 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1939 [output writeInt32Array:fieldNumber values:array tag:tag]; 1940 } else if (fieldType == GPBFieldTypeSingle) { 1941 [output writeInt32:fieldNumber 1942 value:GPBGetMessageInt32Field(self, field)]; 1943 } else { // fieldType == GPBFieldTypeMap 1944 // Exact type here doesn't matter. 1945 GPBInt32Int32Dictionary *dict = 1946 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1947 [dict writeToCodedOutputStream:output asField:field]; 1948 } 1949 break; 1950 1951//%PDDM-EXPAND FIELD_CASE(Int64, Int64) 1952// This block of code is generated, do not edit it directly. 1953 1954 case GPBDataTypeInt64: 1955 if (fieldType == GPBFieldTypeRepeated) { 1956 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1957 GPBInt64Array *array = 1958 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1959 [output writeInt64Array:fieldNumber values:array tag:tag]; 1960 } else if (fieldType == GPBFieldTypeSingle) { 1961 [output writeInt64:fieldNumber 1962 value:GPBGetMessageInt64Field(self, field)]; 1963 } else { // fieldType == GPBFieldTypeMap 1964 // Exact type here doesn't matter. 1965 GPBInt32Int64Dictionary *dict = 1966 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1967 [dict writeToCodedOutputStream:output asField:field]; 1968 } 1969 break; 1970 1971//%PDDM-EXPAND FIELD_CASE(SInt32, Int32) 1972// This block of code is generated, do not edit it directly. 1973 1974 case GPBDataTypeSInt32: 1975 if (fieldType == GPBFieldTypeRepeated) { 1976 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1977 GPBInt32Array *array = 1978 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1979 [output writeSInt32Array:fieldNumber values:array tag:tag]; 1980 } else if (fieldType == GPBFieldTypeSingle) { 1981 [output writeSInt32:fieldNumber 1982 value:GPBGetMessageInt32Field(self, field)]; 1983 } else { // fieldType == GPBFieldTypeMap 1984 // Exact type here doesn't matter. 1985 GPBInt32Int32Dictionary *dict = 1986 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1987 [dict writeToCodedOutputStream:output asField:field]; 1988 } 1989 break; 1990 1991//%PDDM-EXPAND FIELD_CASE(SInt64, Int64) 1992// This block of code is generated, do not edit it directly. 1993 1994 case GPBDataTypeSInt64: 1995 if (fieldType == GPBFieldTypeRepeated) { 1996 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1997 GPBInt64Array *array = 1998 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1999 [output writeSInt64Array:fieldNumber values:array tag:tag]; 2000 } else if (fieldType == GPBFieldTypeSingle) { 2001 [output writeSInt64:fieldNumber 2002 value:GPBGetMessageInt64Field(self, field)]; 2003 } else { // fieldType == GPBFieldTypeMap 2004 // Exact type here doesn't matter. 2005 GPBInt32Int64Dictionary *dict = 2006 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2007 [dict writeToCodedOutputStream:output asField:field]; 2008 } 2009 break; 2010 2011//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) 2012// This block of code is generated, do not edit it directly. 2013 2014 case GPBDataTypeUInt32: 2015 if (fieldType == GPBFieldTypeRepeated) { 2016 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 2017 GPBUInt32Array *array = 2018 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2019 [output writeUInt32Array:fieldNumber values:array tag:tag]; 2020 } else if (fieldType == GPBFieldTypeSingle) { 2021 [output writeUInt32:fieldNumber 2022 value:GPBGetMessageUInt32Field(self, field)]; 2023 } else { // fieldType == GPBFieldTypeMap 2024 // Exact type here doesn't matter. 2025 GPBInt32UInt32Dictionary *dict = 2026 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2027 [dict writeToCodedOutputStream:output asField:field]; 2028 } 2029 break; 2030 2031//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) 2032// This block of code is generated, do not edit it directly. 2033 2034 case GPBDataTypeUInt64: 2035 if (fieldType == GPBFieldTypeRepeated) { 2036 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 2037 GPBUInt64Array *array = 2038 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2039 [output writeUInt64Array:fieldNumber values:array tag:tag]; 2040 } else if (fieldType == GPBFieldTypeSingle) { 2041 [output writeUInt64:fieldNumber 2042 value:GPBGetMessageUInt64Field(self, field)]; 2043 } else { // fieldType == GPBFieldTypeMap 2044 // Exact type here doesn't matter. 2045 GPBInt32UInt64Dictionary *dict = 2046 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2047 [dict writeToCodedOutputStream:output asField:field]; 2048 } 2049 break; 2050 2051//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) 2052// This block of code is generated, do not edit it directly. 2053 2054 case GPBDataTypeEnum: 2055 if (fieldType == GPBFieldTypeRepeated) { 2056 uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 2057 GPBEnumArray *array = 2058 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2059 [output writeEnumArray:fieldNumber values:array tag:tag]; 2060 } else if (fieldType == GPBFieldTypeSingle) { 2061 [output writeEnum:fieldNumber 2062 value:GPBGetMessageInt32Field(self, field)]; 2063 } else { // fieldType == GPBFieldTypeMap 2064 // Exact type here doesn't matter. 2065 GPBInt32EnumDictionary *dict = 2066 GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2067 [dict writeToCodedOutputStream:output asField:field]; 2068 } 2069 break; 2070 2071//%PDDM-EXPAND FIELD_CASE2(Bytes) 2072// This block of code is generated, do not edit it directly. 2073 2074 case GPBDataTypeBytes: 2075 if (fieldType == GPBFieldTypeRepeated) { 2076 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2077 [output writeBytesArray:fieldNumber values:array]; 2078 } else if (fieldType == GPBFieldTypeSingle) { 2079 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 2080 // again. 2081 [output writeBytes:fieldNumber 2082 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 2083 } else { // fieldType == GPBFieldTypeMap 2084 // Exact type here doesn't matter. 2085 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2086 GPBDataType mapKeyDataType = field.mapKeyDataType; 2087 if (mapKeyDataType == GPBDataTypeString) { 2088 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 2089 } else { 2090 [dict writeToCodedOutputStream:output asField:field]; 2091 } 2092 } 2093 break; 2094 2095//%PDDM-EXPAND FIELD_CASE2(String) 2096// This block of code is generated, do not edit it directly. 2097 2098 case GPBDataTypeString: 2099 if (fieldType == GPBFieldTypeRepeated) { 2100 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2101 [output writeStringArray:fieldNumber values:array]; 2102 } else if (fieldType == GPBFieldTypeSingle) { 2103 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 2104 // again. 2105 [output writeString:fieldNumber 2106 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 2107 } else { // fieldType == GPBFieldTypeMap 2108 // Exact type here doesn't matter. 2109 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2110 GPBDataType mapKeyDataType = field.mapKeyDataType; 2111 if (mapKeyDataType == GPBDataTypeString) { 2112 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 2113 } else { 2114 [dict writeToCodedOutputStream:output asField:field]; 2115 } 2116 } 2117 break; 2118 2119//%PDDM-EXPAND FIELD_CASE2(Message) 2120// This block of code is generated, do not edit it directly. 2121 2122 case GPBDataTypeMessage: 2123 if (fieldType == GPBFieldTypeRepeated) { 2124 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2125 [output writeMessageArray:fieldNumber values:array]; 2126 } else if (fieldType == GPBFieldTypeSingle) { 2127 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 2128 // again. 2129 [output writeMessage:fieldNumber 2130 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 2131 } else { // fieldType == GPBFieldTypeMap 2132 // Exact type here doesn't matter. 2133 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2134 GPBDataType mapKeyDataType = field.mapKeyDataType; 2135 if (mapKeyDataType == GPBDataTypeString) { 2136 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 2137 } else { 2138 [dict writeToCodedOutputStream:output asField:field]; 2139 } 2140 } 2141 break; 2142 2143//%PDDM-EXPAND FIELD_CASE2(Group) 2144// This block of code is generated, do not edit it directly. 2145 2146 case GPBDataTypeGroup: 2147 if (fieldType == GPBFieldTypeRepeated) { 2148 NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2149 [output writeGroupArray:fieldNumber values:array]; 2150 } else if (fieldType == GPBFieldTypeSingle) { 2151 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 2152 // again. 2153 [output writeGroup:fieldNumber 2154 value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 2155 } else { // fieldType == GPBFieldTypeMap 2156 // Exact type here doesn't matter. 2157 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2158 GPBDataType mapKeyDataType = field.mapKeyDataType; 2159 if (mapKeyDataType == GPBDataTypeString) { 2160 GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 2161 } else { 2162 [dict writeToCodedOutputStream:output asField:field]; 2163 } 2164 } 2165 break; 2166 2167//%PDDM-EXPAND-END (18 expansions) 2168 2169 // clang-format on 2170 } 2171} 2172 2173#pragma mark - Extensions 2174 2175- (id)getExtension:(GPBExtensionDescriptor *)extension { 2176 CheckExtension(self, extension); 2177 id value = [extensionMap_ objectForKey:extension]; 2178 if (value != nil) { 2179 return value; 2180 } 2181 2182 // No default for repeated. 2183 if (extension.isRepeated) { 2184 return nil; 2185 } 2186 // Non messages get their default. 2187 if (!GPBExtensionIsMessage(extension)) { 2188 return extension.defaultValue; 2189 } 2190 2191 // Check for an autocreated value. 2192 os_unfair_lock_lock(&readOnlyLock_); 2193 value = [autocreatedExtensionMap_ objectForKey:extension]; 2194 if (!value) { 2195 // Auto create the message extensions to match normal fields. 2196 value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, extension); 2197 2198 if (autocreatedExtensionMap_ == nil) { 2199 autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; 2200 } 2201 2202 // We can't simply call setExtension here because that would clear the new 2203 // value's autocreator. 2204 [autocreatedExtensionMap_ setObject:value forKey:extension]; 2205 [value release]; 2206 } 2207 2208 os_unfair_lock_unlock(&readOnlyLock_); 2209 return value; 2210} 2211 2212- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { 2213 // This is an internal method so we don't need to call CheckExtension(). 2214 return [extensionMap_ objectForKey:extension]; 2215} 2216 2217- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { 2218#if defined(DEBUG) && DEBUG 2219 CheckExtension(self, extension); 2220#endif // DEBUG 2221 return nil != [extensionMap_ objectForKey:extension]; 2222} 2223 2224- (NSArray *)extensionsCurrentlySet { 2225 return [extensionMap_ allKeys]; 2226} 2227 2228- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output 2229 range:(GPBExtensionRange)range 2230 sortedExtensions:(NSArray *)sortedExtensions { 2231 uint32_t start = range.start; 2232 uint32_t end = range.end; 2233 for (GPBExtensionDescriptor *extension in sortedExtensions) { 2234 uint32_t fieldNumber = extension.fieldNumber; 2235 if (fieldNumber < start) { 2236 continue; 2237 } 2238 if (fieldNumber >= end) { 2239 break; 2240 } 2241 id value = [extensionMap_ objectForKey:extension]; 2242 GPBWriteExtensionValueToOutputStream(extension, value, output); 2243 } 2244} 2245 2246- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { 2247 if (!value) { 2248 [self clearExtension:extension]; 2249 return; 2250 } 2251 2252 CheckExtension(self, extension); 2253 2254 if (extension.repeated) { 2255 [NSException raise:NSInvalidArgumentException 2256 format:@"Must call addExtension() for repeated types."]; 2257 } 2258 2259 if (extensionMap_ == nil) { 2260 extensionMap_ = [[NSMutableDictionary alloc] init]; 2261 } 2262 2263 // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. 2264 // Without it, the compiler complains we're passing an id nullable when 2265 // setObject:forKey: requires a id nonnull for the value. The check for 2266 // !value at the start of the method ensures it isn't nil, but the check 2267 // isn't smart enough to realize that. 2268 [extensionMap_ setObject:(id)value forKey:extension]; 2269 2270 GPBExtensionDescriptor *descriptor = extension; 2271 2272 if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { 2273 GPBMessage *autocreatedValue = [[autocreatedExtensionMap_ objectForKey:extension] retain]; 2274 // Must remove from the map before calling GPBClearMessageAutocreator() so 2275 // that GPBClearMessageAutocreator() knows its safe to clear. 2276 [autocreatedExtensionMap_ removeObjectForKey:extension]; 2277 GPBClearMessageAutocreator(autocreatedValue); 2278 [autocreatedValue release]; 2279 } 2280 2281 GPBBecomeVisibleToAutocreator(self); 2282} 2283 2284- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { 2285 CheckExtension(self, extension); 2286 2287 if (!extension.repeated) { 2288 [NSException raise:NSInvalidArgumentException 2289 format:@"Must call setExtension() for singular types."]; 2290 } 2291 2292 if (extensionMap_ == nil) { 2293 extensionMap_ = [[NSMutableDictionary alloc] init]; 2294 } 2295 NSMutableArray *list = [extensionMap_ objectForKey:extension]; 2296 if (list == nil) { 2297 list = [NSMutableArray array]; 2298 [extensionMap_ setObject:list forKey:extension]; 2299 } 2300 2301 [list addObject:value]; 2302 GPBBecomeVisibleToAutocreator(self); 2303} 2304 2305- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)idx value:(id)value { 2306 CheckExtension(self, extension); 2307 2308 if (!extension.repeated) { 2309 [NSException raise:NSInvalidArgumentException 2310 format:@"Must call setExtension() for singular types."]; 2311 } 2312 2313 if (extensionMap_ == nil) { 2314 extensionMap_ = [[NSMutableDictionary alloc] init]; 2315 } 2316 2317 NSMutableArray *list = [extensionMap_ objectForKey:extension]; 2318 2319 [list replaceObjectAtIndex:idx withObject:value]; 2320 GPBBecomeVisibleToAutocreator(self); 2321} 2322 2323- (void)clearExtension:(GPBExtensionDescriptor *)extension { 2324 CheckExtension(self, extension); 2325 2326 // Only become visible if there was actually a value to clear. 2327 if ([extensionMap_ objectForKey:extension]) { 2328 [extensionMap_ removeObjectForKey:extension]; 2329 GPBBecomeVisibleToAutocreator(self); 2330 } 2331} 2332 2333#pragma mark - mergeFrom 2334 2335- (void)mergeFromData:(NSData *)data extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry { 2336 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 2337 @try { 2338 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; 2339 } @finally { 2340 [input release]; 2341 } 2342} 2343 2344- (BOOL)mergeFromData:(NSData *)data 2345 extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry 2346 error:(NSError **)errorPtr { 2347 GPBBecomeVisibleToAutocreator(self); 2348 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 2349 @try { 2350 [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; 2351 [input checkLastTagWas:0]; 2352 if (errorPtr) { 2353 *errorPtr = nil; 2354 } 2355 } @catch (NSException *exception) { 2356 [input release]; 2357 if (errorPtr) { 2358 *errorPtr = ErrorFromException(exception); 2359 } 2360 return NO; 2361 } 2362 [input release]; 2363 return YES; 2364} 2365 2366#pragma mark - Parse From Data Support 2367 2368+ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { 2369 return [self parseFromData:data extensionRegistry:nil error:errorPtr]; 2370} 2371 2372+ (instancetype)parseFromData:(NSData *)data 2373 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 2374 error:(NSError **)errorPtr { 2375 return [[[self alloc] initWithData:data extensionRegistry:extensionRegistry 2376 error:errorPtr] autorelease]; 2377} 2378 2379+ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input 2380 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 2381 error:(NSError **)errorPtr { 2382 return [[[self alloc] initWithCodedInputStream:input 2383 extensionRegistry:extensionRegistry 2384 error:errorPtr] autorelease]; 2385} 2386 2387#pragma mark - Parse Delimited From Data Support 2388 2389+ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input 2390 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 2391 error:(NSError **)errorPtr { 2392 GPBCodedInputStreamState *state = &input->state_; 2393 // This doesn't completely match the C++, but if the stream has nothing, just make an empty 2394 // message. 2395 if (GPBCodedInputStreamIsAtEnd(state)) { 2396 return [[[self alloc] init] autorelease]; 2397 } 2398 2399 // Manually extract the data and parse it. If we read a varint and push a limit, that consumes 2400 // some of the recursion buffer which isn't correct, it also can result in a change in error 2401 // codes for attempts to parse partial data; and there are projects sensitive to that, so this 2402 // maintains existing error flows. 2403 2404 // Extract the data, but in a "no copy" mode since we will immediately parse it so this NSData 2405 // is transient. 2406 NSData *data = nil; 2407 @try { 2408 data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); 2409 } @catch (NSException *exception) { 2410 if (errorPtr) { 2411 *errorPtr = ErrorFromException(exception); 2412 } 2413 return nil; 2414 } 2415 2416 GPBMessage *result = [self parseFromData:data extensionRegistry:extensionRegistry error:errorPtr]; 2417 [data release]; 2418 if (result && errorPtr) { 2419 *errorPtr = nil; 2420 } 2421 return result; 2422} 2423 2424#pragma mark - Unknown Field Support 2425 2426- (GPBUnknownFieldSet *)unknownFields { 2427 @synchronized(self) { 2428 if (unknownFieldData_) { 2429#if defined(DEBUG) && DEBUG 2430 NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set"); 2431#endif 2432 unknownFields_ = [[GPBUnknownFieldSet alloc] init]; 2433 MergeUnknownFieldDataIntoFieldSet(self, unknownFieldData_, nil); 2434 [unknownFieldData_ release]; 2435 unknownFieldData_ = nil; 2436 } 2437 return unknownFields_; 2438 } // @synchronized(self) 2439} 2440 2441- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { 2442 if (unknownFields != unknownFields_ || unknownFieldData_ != nil) { 2443 // Changing sets or clearing. 2444 [unknownFieldData_ release]; 2445 unknownFieldData_ = nil; 2446 [unknownFields_ release]; 2447 unknownFields_ = [unknownFields copy]; 2448 GPBBecomeVisibleToAutocreator(self); 2449 } 2450} 2451 2452- (void)parseMessageSet:(GPBCodedInputStream *)input 2453 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry { 2454 uint32_t typeId = 0; 2455 NSData *rawBytes = nil; 2456 GPBCodedInputStreamState *state = &input->state_; 2457 BOOL gotType = NO; 2458 BOOL gotBytes = NO; 2459 while (true) { 2460 uint32_t tag = GPBCodedInputStreamReadTag(state); 2461 if (tag == GPBWireFormatMessageSetItemEndTag || tag == 0) { 2462 break; 2463 } 2464 2465 if (tag == GPBWireFormatMessageSetTypeIdTag) { 2466 uint32_t tmp = GPBCodedInputStreamReadUInt32(state); 2467 // Spec says only use the first value. 2468 if (!gotType) { 2469 gotType = YES; 2470 typeId = tmp; 2471 } 2472 } else if (tag == GPBWireFormatMessageSetMessageTag) { 2473 if (gotBytes) { 2474 // Skip over the payload instead of collecting it. 2475 [input skipField:tag]; 2476 } else { 2477 rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; 2478 gotBytes = YES; 2479 } 2480 } else { 2481 // Don't capture unknowns within the message set impl group. 2482 if (![input skipField:tag]) { 2483 break; 2484 } 2485 } 2486 } 2487 2488 // If we get here because of end of input (tag zero) or the wrong end tag (within the skipField:), 2489 // this will error. 2490 GPBCodedInputStreamCheckLastTagWas(state, GPBWireFormatMessageSetItemEndTag); 2491 2492 if (!gotType || !gotBytes) { 2493 // upb_Decoder_DecodeMessageSetItem does't keep this partial as an unknown field, it just drops 2494 // it, so do the same thing. 2495 return; 2496 } 2497 2498 GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:[self descriptor] 2499 fieldNumber:typeId]; 2500 if (extension) { 2501#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 2502 NSAssert(extension.dataType == GPBDataTypeMessage, 2503 @"Internal Error: MessageSet extension must be a message field."); 2504 NSAssert(GPBExtensionIsWireFormat(extension->description_), 2505 @"Internal Error: MessageSet extension must have message_set_wire_format set."); 2506 NSAssert(!GPBExtensionIsRepeated(extension->description_), 2507 @"Internal Error: MessageSet extension can't be repeated."); 2508#endif 2509 // Look up the existing one to merge to or create a new one. 2510 GPBMessage *targetMessage = [self getExistingExtension:extension]; 2511 if (!targetMessage) { 2512 GPBDescriptor *descriptor = [extension.msgClass descriptor]; 2513 targetMessage = [[descriptor.messageClass alloc] init]; 2514 [self setExtension:extension value:targetMessage]; 2515 [targetMessage release]; 2516 } 2517 GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes]; 2518 @try { 2519 [targetMessage mergeFromCodedInputStream:newInput 2520 extensionRegistry:extensionRegistry 2521 endingTag:0]; 2522 } @finally { 2523 [newInput release]; 2524 } 2525 } else { 2526 // The extension isn't in the registry, but it was well formed, so the whole group structure 2527 // get preserved as an unknown field. 2528 2529 // rawBytes was created via a NoCopy, so it can be reusing a 2530 // subrange of another NSData that might go out of scope as things 2531 // unwind, so a copy is needed to ensure what is saved in the 2532 // unknown fields stays valid. 2533 NSData *cloned = [NSData dataWithData:rawBytes]; 2534 AddUnknownMessageSetEntry(self, typeId, cloned); 2535 } 2536} 2537 2538- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { 2539 AddUnknownFieldLengthDelimited(self, fieldNum, data); 2540} 2541 2542#pragma mark - MergeFromCodedInputStream Support 2543 2544static void MergeSingleFieldFromCodedInputStream(GPBMessage *self, GPBFieldDescriptor *field, 2545 GPBCodedInputStream *input, 2546 id<GPBExtensionRegistry> extensionRegistry) { 2547 GPBDataType fieldDataType = GPBGetFieldDataType(field); 2548 switch (fieldDataType) { 2549#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ 2550 case GPBDataType##NAME: { \ 2551 TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ 2552 GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \ 2553 break; \ 2554 } 2555#define CASE_SINGLE_OBJECT(NAME) \ 2556 case GPBDataType##NAME: { \ 2557 id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ 2558 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val); \ 2559 break; \ 2560 } 2561 CASE_SINGLE_POD(Bool, BOOL, Bool) 2562 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) 2563 CASE_SINGLE_POD(SFixed32, int32_t, Int32) 2564 CASE_SINGLE_POD(Float, float, Float) 2565 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) 2566 CASE_SINGLE_POD(SFixed64, int64_t, Int64) 2567 CASE_SINGLE_POD(Double, double, Double) 2568 CASE_SINGLE_POD(Int32, int32_t, Int32) 2569 CASE_SINGLE_POD(Int64, int64_t, Int64) 2570 CASE_SINGLE_POD(SInt32, int32_t, Int32) 2571 CASE_SINGLE_POD(SInt64, int64_t, Int64) 2572 CASE_SINGLE_POD(UInt32, uint32_t, UInt32) 2573 CASE_SINGLE_POD(UInt64, uint64_t, UInt64) 2574 CASE_SINGLE_OBJECT(Bytes) 2575 CASE_SINGLE_OBJECT(String) 2576#undef CASE_SINGLE_POD 2577#undef CASE_SINGLE_OBJECT 2578 2579 case GPBDataTypeMessage: { 2580 if (GPBGetHasIvarField(self, field)) { 2581 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has 2582 // check again. 2583 GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2584 [input readMessage:message extensionRegistry:extensionRegistry]; 2585 } else { 2586 GPBMessage *message = [[field.msgClass alloc] init]; 2587 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2588 [input readMessage:message extensionRegistry:extensionRegistry]; 2589 } 2590 break; 2591 } 2592 2593 case GPBDataTypeGroup: { 2594 if (GPBGetHasIvarField(self, field)) { 2595 // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has 2596 // check again. 2597 GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2598 [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry]; 2599 } else { 2600 GPBMessage *message = [[field.msgClass alloc] init]; 2601 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2602 [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry]; 2603 } 2604 break; 2605 } 2606 2607 case GPBDataTypeEnum: { 2608 int32_t val = GPBCodedInputStreamReadEnum(&input->state_); 2609 if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { 2610 GPBSetInt32IvarWithFieldPrivate(self, field, val); 2611 } else { 2612 AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); 2613 } 2614 } 2615 } // switch 2616} 2617 2618static void MergeRepeatedPackedFieldFromCodedInputStream(GPBMessage *self, 2619 GPBFieldDescriptor *field, 2620 GPBCodedInputStream *input) { 2621 GPBDataType fieldDataType = GPBGetFieldDataType(field); 2622 GPBCodedInputStreamState *state = &input->state_; 2623 id genericArray = GetOrCreateArrayIvarWithField(self, field); 2624 int32_t length = GPBCodedInputStreamReadInt32(state); 2625 size_t limit = GPBCodedInputStreamPushLimit(state, length); 2626 while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { 2627 switch (fieldDataType) { 2628#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ 2629 case GPBDataType##NAME: { \ 2630 TYPE val = GPBCodedInputStreamRead##NAME(state); \ 2631 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ 2632 break; \ 2633 } 2634 CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) 2635 CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) 2636 CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) 2637 CASE_REPEATED_PACKED_POD(Float, float, Float) 2638 CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) 2639 CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) 2640 CASE_REPEATED_PACKED_POD(Double, double, Double) 2641 CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) 2642 CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) 2643 CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) 2644 CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) 2645 CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) 2646 CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) 2647#undef CASE_REPEATED_PACKED_POD 2648 2649 case GPBDataTypeBytes: 2650 case GPBDataTypeString: 2651 case GPBDataTypeMessage: 2652 case GPBDataTypeGroup: 2653 NSCAssert(NO, @"Non primitive types can't be packed"); 2654 break; 2655 2656 case GPBDataTypeEnum: { 2657 int32_t val = GPBCodedInputStreamReadEnum(state); 2658 if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { 2659 [(GPBEnumArray *)genericArray addRawValue:val]; 2660 } else { 2661 AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); 2662 } 2663 break; 2664 } 2665 } // switch 2666 } // while(BytesUntilLimit() > 0) 2667 GPBCodedInputStreamPopLimit(state, limit); 2668} 2669 2670static void MergeRepeatedNotPackedFieldFromCodedInputStream( 2671 GPBMessage *self, GPBFieldDescriptor *field, GPBCodedInputStream *input, 2672 id<GPBExtensionRegistry> extensionRegistry) { 2673 GPBCodedInputStreamState *state = &input->state_; 2674 id genericArray = GetOrCreateArrayIvarWithField(self, field); 2675 switch (GPBGetFieldDataType(field)) { 2676#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ 2677 case GPBDataType##NAME: { \ 2678 TYPE val = GPBCodedInputStreamRead##NAME(state); \ 2679 [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ 2680 break; \ 2681 } 2682#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ 2683 case GPBDataType##NAME: { \ 2684 id val = GPBCodedInputStreamReadRetained##NAME(state); \ 2685 [(NSMutableArray *)genericArray addObject:val]; \ 2686 [val release]; \ 2687 break; \ 2688 } 2689 CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) 2690 CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) 2691 CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) 2692 CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) 2693 CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) 2694 CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) 2695 CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) 2696 CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) 2697 CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) 2698 CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) 2699 CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) 2700 CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) 2701 CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) 2702 CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) 2703 CASE_REPEATED_NOT_PACKED_OBJECT(String) 2704#undef CASE_REPEATED_NOT_PACKED_POD 2705#undef CASE_NOT_PACKED_OBJECT 2706 case GPBDataTypeMessage: { 2707 GPBMessage *message = [[field.msgClass alloc] init]; 2708 [(NSMutableArray *)genericArray addObject:message]; 2709 // The array will now retain message, so go ahead and release it in case 2710 // -readMessage:extensionRegistry: throws so it won't be leaked. 2711 [message release]; 2712 [input readMessage:message extensionRegistry:extensionRegistry]; 2713 break; 2714 } 2715 case GPBDataTypeGroup: { 2716 GPBMessage *message = [[field.msgClass alloc] init]; 2717 [(NSMutableArray *)genericArray addObject:message]; 2718 // The array will now retain message, so go ahead and release it in case 2719 // -readGroup:extensionRegistry: throws so it won't be leaked. 2720 [message release]; 2721 [input readGroup:GPBFieldNumber(field) message:message extensionRegistry:extensionRegistry]; 2722 break; 2723 } 2724 case GPBDataTypeEnum: { 2725 int32_t val = GPBCodedInputStreamReadEnum(state); 2726 if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { 2727 [(GPBEnumArray *)genericArray addRawValue:val]; 2728 } else { 2729 AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); 2730 } 2731 break; 2732 } 2733 } // switch 2734} 2735 2736- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input 2737 extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry 2738 endingTag:(uint32_t)endingTag { 2739#if defined(DEBUG) && DEBUG 2740 NSAssert(endingTag == 0 || GPBWireFormatGetTagWireType(endingTag) == GPBWireFormatEndGroup, 2741 @"endingTag should have been an endGroup tag"); 2742#endif // DEBUG 2743 GPBDescriptor *descriptor = [self descriptor]; 2744 GPBCodedInputStreamState *state = &input->state_; 2745 uint32_t tag = 0; 2746 NSUInteger startingIndex = 0; 2747 NSArray *fields = descriptor->fields_; 2748 BOOL isMessageSetWireFormat = descriptor.isWireFormat; 2749 NSUInteger numFields = fields.count; 2750 while (YES) { 2751 BOOL merged = NO; 2752 tag = GPBCodedInputStreamReadTag(state); 2753 if (tag == endingTag || tag == 0) { 2754 // If we got to the end (tag zero), when we were expecting the end group, this will 2755 // raise the error. 2756 GPBCodedInputStreamCheckLastTagWas(state, endingTag); 2757 return; 2758 } 2759 for (NSUInteger i = 0; i < numFields; ++i) { 2760 if (startingIndex >= numFields) startingIndex = 0; 2761 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; 2762 if (GPBFieldTag(fieldDescriptor) == tag) { 2763 GPBFieldType fieldType = fieldDescriptor.fieldType; 2764 if (fieldType == GPBFieldTypeSingle) { 2765 MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, input, extensionRegistry); 2766 // Well formed protos will only have a single field once, advance 2767 // the starting index to the next field. 2768 startingIndex += 1; 2769 } else if (fieldType == GPBFieldTypeRepeated) { 2770 if (fieldDescriptor.isPackable) { 2771 MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input); 2772 // Well formed protos will only have a repeated field that is 2773 // packed once, advance the starting index to the next field. 2774 startingIndex += 1; 2775 } else { 2776 MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input, 2777 extensionRegistry); 2778 } 2779 } else { // fieldType == GPBFieldTypeMap 2780 // GPB*Dictionary or NSDictionary, exact type doesn't matter at this 2781 // point. 2782 id map = GetOrCreateMapIvarWithField(self, fieldDescriptor); 2783 [input readMapEntry:map 2784 extensionRegistry:extensionRegistry 2785 field:fieldDescriptor 2786 parentMessage:self]; 2787 } 2788 merged = YES; 2789 break; 2790 } else { 2791 startingIndex += 1; 2792 } 2793 } // for(i < numFields) 2794 2795 if (merged) continue; // On to the next tag 2796 2797 // Primitive, repeated types can be packed or unpacked on the wire, and 2798 // are parsed either way. The above loop covered tag in the preferred 2799 // for, so this need to check the alternate form. 2800 for (NSUInteger i = 0; i < numFields; ++i) { 2801 if (startingIndex >= numFields) startingIndex = 0; 2802 GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; 2803 if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && 2804 !GPBFieldDataTypeIsObject(fieldDescriptor) && 2805 (GPBFieldAlternateTag(fieldDescriptor) == tag)) { 2806 BOOL alternateIsPacked = !fieldDescriptor.isPackable; 2807 if (alternateIsPacked) { 2808 MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input); 2809 // Well formed protos will only have a repeated field that is 2810 // packed once, advance the starting index to the next field. 2811 startingIndex += 1; 2812 } else { 2813 MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input, 2814 extensionRegistry); 2815 } 2816 merged = YES; 2817 break; 2818 } else { 2819 startingIndex += 1; 2820 } 2821 } 2822 2823 if (merged) continue; // On to the next tag 2824 2825 if (isMessageSetWireFormat) { 2826 if (GPBWireFormatMessageSetItemTag == tag) { 2827 [self parseMessageSet:input extensionRegistry:extensionRegistry]; 2828 continue; // On to the next tag 2829 } 2830 } else { 2831 // ObjC Runtime currently doesn't track if a message supported extensions, so the check is 2832 // always done. 2833 GPBExtensionDescriptor *extension = 2834 [extensionRegistry extensionForDescriptor:descriptor 2835 fieldNumber:GPBWireFormatGetTagFieldNumber(tag)]; 2836 if (extension) { 2837 GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); 2838 if (extension.wireType == wireType) { 2839 ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry, 2840 self); 2841 continue; // On to the next tag 2842 } 2843 // Primitive, repeated types can be packed on unpacked on the wire, and are 2844 // parsed either way. 2845 if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) && 2846 (extension.alternateWireType == wireType)) { 2847 ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry, 2848 self); 2849 continue; // On to the next tag 2850 } 2851 } 2852 } 2853 2854 ParseUnknownField(self, tag, input); 2855 } // while(YES) 2856} 2857 2858#pragma mark - MergeFrom Support 2859 2860- (void)mergeFrom:(GPBMessage *)other { 2861 Class selfClass = [self class]; 2862 Class otherClass = [other class]; 2863 if (!([selfClass isSubclassOfClass:otherClass] || [otherClass isSubclassOfClass:selfClass])) { 2864 [NSException raise:NSInvalidArgumentException 2865 format:@"Classes must match %@ != %@", selfClass, otherClass]; 2866 } 2867 2868 // We assume something will be done and become visible. 2869 GPBBecomeVisibleToAutocreator(self); 2870 2871 GPBDescriptor *descriptor = [[self class] descriptor]; 2872 2873 for (GPBFieldDescriptor *field in descriptor->fields_) { 2874 GPBFieldType fieldType = field.fieldType; 2875 if (fieldType == GPBFieldTypeSingle) { 2876 int32_t hasIndex = GPBFieldHasIndex(field); 2877 uint32_t fieldNumber = GPBFieldNumber(field); 2878 if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { 2879 // Other doesn't have the field set, on to the next. 2880 continue; 2881 } 2882 GPBDataType fieldDataType = GPBGetFieldDataType(field); 2883 switch (fieldDataType) { 2884 case GPBDataTypeBool: 2885 GPBSetBoolIvarWithFieldPrivate(self, field, GPBGetMessageBoolField(other, field)); 2886 break; 2887 case GPBDataTypeSFixed32: 2888 case GPBDataTypeEnum: 2889 case GPBDataTypeInt32: 2890 case GPBDataTypeSInt32: 2891 GPBSetInt32IvarWithFieldPrivate(self, field, GPBGetMessageInt32Field(other, field)); 2892 break; 2893 case GPBDataTypeFixed32: 2894 case GPBDataTypeUInt32: 2895 GPBSetUInt32IvarWithFieldPrivate(self, field, GPBGetMessageUInt32Field(other, field)); 2896 break; 2897 case GPBDataTypeSFixed64: 2898 case GPBDataTypeInt64: 2899 case GPBDataTypeSInt64: 2900 GPBSetInt64IvarWithFieldPrivate(self, field, GPBGetMessageInt64Field(other, field)); 2901 break; 2902 case GPBDataTypeFixed64: 2903 case GPBDataTypeUInt64: 2904 GPBSetUInt64IvarWithFieldPrivate(self, field, GPBGetMessageUInt64Field(other, field)); 2905 break; 2906 case GPBDataTypeFloat: 2907 GPBSetFloatIvarWithFieldPrivate(self, field, GPBGetMessageFloatField(other, field)); 2908 break; 2909 case GPBDataTypeDouble: 2910 GPBSetDoubleIvarWithFieldPrivate(self, field, GPBGetMessageDoubleField(other, field)); 2911 break; 2912 case GPBDataTypeBytes: 2913 case GPBDataTypeString: { 2914 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2915 GPBSetObjectIvarWithFieldPrivate(self, field, otherVal); 2916 break; 2917 } 2918 case GPBDataTypeMessage: 2919 case GPBDataTypeGroup: { 2920 id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2921 if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { 2922 GPBMessage *message = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2923 [message mergeFrom:otherVal]; 2924 } else { 2925 GPBMessage *message = [otherVal copy]; 2926 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2927 } 2928 break; 2929 } 2930 } // switch() 2931 } else if (fieldType == GPBFieldTypeRepeated) { 2932 // In the case of a list, they need to be appended, and there is no 2933 // _hasIvar to worry about setting. 2934 id otherArray = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2935 if (otherArray) { 2936 GPBDataType fieldDataType = field->description_->dataType; 2937 if (GPBDataTypeIsObject(fieldDataType)) { 2938 NSMutableArray *resultArray = GetOrCreateArrayIvarWithField(self, field); 2939 [resultArray addObjectsFromArray:otherArray]; 2940 } else if (fieldDataType == GPBDataTypeEnum) { 2941 GPBEnumArray *resultArray = GetOrCreateArrayIvarWithField(self, field); 2942 [resultArray addRawValuesFromArray:otherArray]; 2943 } else { 2944 // The array type doesn't matter, that all implement 2945 // -addValuesFromArray:. 2946 GPBInt32Array *resultArray = GetOrCreateArrayIvarWithField(self, field); 2947 [resultArray addValuesFromArray:otherArray]; 2948 } 2949 } 2950 } else { // fieldType = GPBFieldTypeMap 2951 // In the case of a map, they need to be merged, and there is no 2952 // _hasIvar to worry about setting. 2953 id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2954 if (otherDict) { 2955 GPBDataType keyDataType = field.mapKeyDataType; 2956 GPBDataType valueDataType = field->description_->dataType; 2957 if (GPBDataTypeIsObject(keyDataType) && GPBDataTypeIsObject(valueDataType)) { 2958 NSMutableDictionary *resultDict = GetOrCreateMapIvarWithField(self, field); 2959 [resultDict addEntriesFromDictionary:otherDict]; 2960 } else if (valueDataType == GPBDataTypeEnum) { 2961 // The exact type doesn't matter, just need to know it is a 2962 // GPB*EnumDictionary. 2963 GPBInt32EnumDictionary *resultDict = GetOrCreateMapIvarWithField(self, field); 2964 [resultDict addRawEntriesFromDictionary:otherDict]; 2965 } else { 2966 // The exact type doesn't matter, they all implement 2967 // -addEntriesFromDictionary:. 2968 GPBInt32Int32Dictionary *resultDict = GetOrCreateMapIvarWithField(self, field); 2969 [resultDict addEntriesFromDictionary:otherDict]; 2970 } 2971 } 2972 } // if (fieldType)..else if...else 2973 } // for(fields) 2974 2975 // Unknown fields. 2976 if (unknownFields_) { 2977#if defined(DEBUG) && DEBUG 2978 NSAssert(unknownFieldData_ == nil, @"Internal error both unknown states were set"); 2979#endif 2980 @synchronized(other) { 2981 if (other->unknownFields_) { 2982#if defined(DEBUG) && DEBUG 2983 NSAssert(other->unknownFieldData_ == nil, @"Internal error both unknown states were set"); 2984#endif 2985 [unknownFields_ mergeUnknownFields:other->unknownFields_]; 2986 } else if (other->unknownFieldData_) { 2987 MergeUnknownFieldDataIntoFieldSet(self, other->unknownFieldData_, nil); 2988 } 2989 } // @synchronized(other) 2990 } else { 2991 NSData *otherData = GPBMessageUnknownFieldsData(other); 2992 if (otherData) { 2993 if (unknownFieldData_) { 2994 [unknownFieldData_ appendData:otherData]; 2995 } else { 2996 unknownFieldData_ = [otherData mutableCopy]; 2997 } 2998 } 2999 } 3000 3001 // Extensions 3002 3003 if (other->extensionMap_.count == 0) { 3004 return; 3005 } 3006 3007 if (extensionMap_ == nil) { 3008 extensionMap_ = CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); 3009 } else { 3010 for (GPBExtensionDescriptor *extension in other->extensionMap_) { 3011 id otherValue = [other->extensionMap_ objectForKey:extension]; 3012 id value = [extensionMap_ objectForKey:extension]; 3013 BOOL isMessageExtension = GPBExtensionIsMessage(extension); 3014 3015 if (extension.repeated) { 3016 NSMutableArray *list = value; 3017 if (list == nil) { 3018 list = [[NSMutableArray alloc] init]; 3019 [extensionMap_ setObject:list forKey:extension]; 3020 [list release]; 3021 } 3022 if (isMessageExtension) { 3023 for (GPBMessage *otherListValue in otherValue) { 3024 GPBMessage *copiedValue = [otherListValue copy]; 3025 [list addObject:copiedValue]; 3026 [copiedValue release]; 3027 } 3028 } else { 3029 [list addObjectsFromArray:otherValue]; 3030 } 3031 } else { 3032 if (isMessageExtension) { 3033 if (value) { 3034 [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; 3035 } else { 3036 GPBMessage *copiedValue = [otherValue copy]; 3037 [extensionMap_ setObject:copiedValue forKey:extension]; 3038 [copiedValue release]; 3039 } 3040 } else { 3041 [extensionMap_ setObject:otherValue forKey:extension]; 3042 } 3043 } 3044 3045 if (isMessageExtension && !extension.isRepeated) { 3046 GPBMessage *autocreatedValue = [[autocreatedExtensionMap_ objectForKey:extension] retain]; 3047 // Must remove from the map before calling GPBClearMessageAutocreator() 3048 // so that GPBClearMessageAutocreator() knows its safe to clear. 3049 [autocreatedExtensionMap_ removeObjectForKey:extension]; 3050 GPBClearMessageAutocreator(autocreatedValue); 3051 [autocreatedValue release]; 3052 } 3053 } 3054 } 3055} 3056 3057#pragma mark - isEqual: & hash Support 3058 3059- (BOOL)isEqual:(id)other { 3060 if (other == self) { 3061 return YES; 3062 } 3063 if (![other isKindOfClass:[GPBMessage class]]) { 3064 return NO; 3065 } 3066 GPBMessage *otherMsg = other; 3067 GPBDescriptor *descriptor = [[self class] descriptor]; 3068 if ([[otherMsg class] descriptor] != descriptor) { 3069 return NO; 3070 } 3071 uint8_t *selfStorage = (uint8_t *)messageStorage_; 3072 uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_; 3073 3074 for (GPBFieldDescriptor *field in descriptor->fields_) { 3075 if (GPBFieldIsMapOrArray(field)) { 3076 // In the case of a list or map, there is no _hasIvar to worry about. 3077 // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but 3078 // the type doesn't really matter as the objects all support -count and 3079 // -isEqual:. 3080 NSArray *resultMapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 3081 NSArray *otherMapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 3082 // nil and empty are equal 3083 if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { 3084 if (![resultMapOrArray isEqual:otherMapOrArray]) { 3085 return NO; 3086 } 3087 } 3088 } else { // Single field 3089 int32_t hasIndex = GPBFieldHasIndex(field); 3090 uint32_t fieldNum = GPBFieldNumber(field); 3091 BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); 3092 BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); 3093 if (selfHas != otherHas) { 3094 return NO; // Differing has values, not equal. 3095 } 3096 if (!selfHas) { 3097 // Same has values, was no, nothing else to check for this field. 3098 continue; 3099 } 3100 // Now compare the values. 3101 GPBDataType fieldDataType = GPBGetFieldDataType(field); 3102 size_t fieldOffset = field->description_->offset; 3103 switch (fieldDataType) { 3104 case GPBDataTypeBool: { 3105 // Bools are stored in has_bits to avoid needing explicit space in 3106 // the storage structure. 3107 // (the field number passed to the HasIvar helper doesn't really 3108 // matter since the offset is never negative) 3109 BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); 3110 BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); 3111 if (selfValue != otherValue) { 3112 return NO; 3113 } 3114 break; 3115 } 3116 case GPBDataTypeSFixed32: 3117 case GPBDataTypeInt32: 3118 case GPBDataTypeSInt32: 3119 case GPBDataTypeEnum: 3120 case GPBDataTypeFixed32: 3121 case GPBDataTypeUInt32: 3122 case GPBDataTypeFloat: { 3123 GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); 3124 // These are all 32bit, signed/unsigned doesn't matter for equality. 3125 uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; 3126 uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; 3127 if (*selfValPtr != *otherValPtr) { 3128 return NO; 3129 } 3130 break; 3131 } 3132 case GPBDataTypeSFixed64: 3133 case GPBDataTypeInt64: 3134 case GPBDataTypeSInt64: 3135 case GPBDataTypeFixed64: 3136 case GPBDataTypeUInt64: 3137 case GPBDataTypeDouble: { 3138 GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); 3139 // These are all 64bit, signed/unsigned doesn't matter for equality. 3140 uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; 3141 uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; 3142 if (*selfValPtr != *otherValPtr) { 3143 return NO; 3144 } 3145 break; 3146 } 3147 case GPBDataTypeBytes: 3148 case GPBDataTypeString: 3149 case GPBDataTypeMessage: 3150 case GPBDataTypeGroup: { 3151 // Type doesn't matter here, they all implement -isEqual:. 3152 id *selfValPtr = (id *)&selfStorage[fieldOffset]; 3153 id *otherValPtr = (id *)&otherStorage[fieldOffset]; 3154 if (![*selfValPtr isEqual:*otherValPtr]) { 3155 return NO; 3156 } 3157 break; 3158 } 3159 } // switch() 3160 } // if(mapOrArray)...else 3161 } // for(fields) 3162 3163 // nil and empty are equal 3164 if (extensionMap_.count != 0 || otherMsg->extensionMap_.count != 0) { 3165 if (![extensionMap_ isEqual:otherMsg->extensionMap_]) { 3166 return NO; 3167 } 3168 } 3169 3170 // Mutation while another thread is doing read only access is invalid, so the only thing we 3171 // need to guard against is concurrent r/o access, so we can grab the values (and retain them) 3172 // so we have a version to compare against safely incase the second access causes the transform 3173 // between internal states. 3174#pragma clang diagnostic push 3175#pragma clang diagnostic ignored "-Wdeprecated-declarations" 3176 GPBUnknownFieldSet *selfUnknownFields; 3177 NSData *selfUnknownFieldData; 3178 @synchronized(self) { 3179 selfUnknownFields = [unknownFields_ retain]; 3180 selfUnknownFieldData = [unknownFieldData_ retain]; 3181 } 3182 GPBUnknownFieldSet *otherUnknownFields; 3183 NSData *otherUnknownFieldData; 3184 @synchronized(otherMsg) { 3185 otherUnknownFields = [otherMsg->unknownFields_ retain]; 3186 otherUnknownFieldData = [otherMsg->unknownFieldData_ retain]; 3187 } 3188#pragma clang diagnostic pop 3189#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 3190 if (selfUnknownFields) { 3191 NSAssert(selfUnknownFieldData == nil, @"Internal error both unknown states were set"); 3192 } 3193 if (otherUnknownFields) { 3194 NSAssert(otherUnknownFieldData == nil, @"Internal error both unknown states were set"); 3195 } 3196#endif 3197 // Since a developer can set the legacy unknownFieldSet, treat nil and empty as the same. 3198 if (selfUnknownFields && selfUnknownFields.countOfFields == 0) { 3199 [selfUnknownFields release]; 3200 selfUnknownFields = nil; 3201 } 3202 if (otherUnknownFields && otherUnknownFields.countOfFields == 0) { 3203 [otherUnknownFields release]; 3204 otherUnknownFields = nil; 3205 } 3206 3207 BOOL result = YES; 3208 3209 if (selfUnknownFieldData && otherUnknownFieldData) { 3210 // Both had data, compare it. 3211 result = [selfUnknownFieldData isEqual:otherUnknownFieldData]; 3212 } else if (selfUnknownFields && otherUnknownFields) { 3213 // Both had fields set, compare them. 3214 result = [selfUnknownFields isEqual:otherUnknownFields]; 3215 } else { 3216 // At this point, we're done to one have a set/nothing, and the other having data/nothing. 3217#pragma clang diagnostic push 3218#pragma clang diagnostic ignored "-Wdeprecated-declarations" 3219 GPBUnknownFieldSet *theSet = selfUnknownFields ? selfUnknownFields : otherUnknownFields; 3220 NSData *theData = selfUnknownFieldData ? selfUnknownFieldData : otherUnknownFieldData; 3221 if (theSet) { 3222 if (theData) { 3223 GPBUnknownFieldSet *tempSet = [[GPBUnknownFieldSet alloc] init]; 3224 MergeUnknownFieldDataIntoFieldSet(self, theData, tempSet); 3225 result = [tempSet isEqual:theSet]; 3226 [tempSet release]; 3227 } else { 3228 result = NO; 3229 } 3230 } else { 3231 // It was a data/nothing and nothing, so they equal if the other didn't have data. 3232 result = theData == nil; 3233 } 3234#pragma clang diagnostic pop 3235 } 3236 3237 [selfUnknownFields release]; 3238 [selfUnknownFieldData release]; 3239 [otherUnknownFields release]; 3240 [otherUnknownFieldData release]; 3241 return result; 3242} 3243 3244// It is very difficult to implement a generic hash for ProtoBuf messages that 3245// will perform well. If you need hashing on your ProtoBufs (eg you are using 3246// them as dictionary keys) you will probably want to implement a ProtoBuf 3247// message specific hash as a category on your protobuf class. Do not make it a 3248// category on GPBMessage as you will conflict with this hash, and will possibly 3249// override hash for all generated protobufs. A good implementation of hash will 3250// be really fast, so we would recommend only hashing protobufs that have an 3251// identifier field of some kind that you can easily hash. If you implement 3252// hash, we would strongly recommend overriding isEqual: in your category as 3253// well, as the default implementation of isEqual: is extremely slow, and may 3254// drastically affect performance in large sets. 3255- (NSUInteger)hash { 3256 GPBDescriptor *descriptor = [[self class] descriptor]; 3257 const NSUInteger prime = 19; 3258 uint8_t *storage = (uint8_t *)messageStorage_; 3259 3260 // Start with the descriptor and then mix it with some instance info. 3261 // Hopefully that will give a spread based on classes and what fields are set. 3262 NSUInteger result = (NSUInteger)descriptor; 3263 3264 for (GPBFieldDescriptor *field in descriptor->fields_) { 3265 if (GPBFieldIsMapOrArray(field)) { 3266 // Exact type doesn't matter, just check if there are any elements. 3267 NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 3268 NSUInteger count = mapOrArray.count; 3269 if (count) { 3270 // NSArray/NSDictionary use count, use the field number and the count. 3271 result = prime * result + GPBFieldNumber(field); 3272 result = prime * result + count; 3273 } 3274 } else if (GPBGetHasIvarField(self, field)) { 3275 // Just using the field number seemed simple/fast, but then a small 3276 // message class where all the same fields are always set (to different 3277 // things would end up all with the same hash, so pull in some data). 3278 GPBDataType fieldDataType = GPBGetFieldDataType(field); 3279 size_t fieldOffset = field->description_->offset; 3280 switch (fieldDataType) { 3281 case GPBDataTypeBool: { 3282 // Bools are stored in has_bits to avoid needing explicit space in 3283 // the storage structure. 3284 // (the field number passed to the HasIvar helper doesn't really 3285 // matter since the offset is never negative) 3286 BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); 3287 result = prime * result + value; 3288 break; 3289 } 3290 case GPBDataTypeSFixed32: 3291 case GPBDataTypeInt32: 3292 case GPBDataTypeSInt32: 3293 case GPBDataTypeEnum: 3294 case GPBDataTypeFixed32: 3295 case GPBDataTypeUInt32: 3296 case GPBDataTypeFloat: { 3297 GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); 3298 // These are all 32bit, just mix it in. 3299 uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; 3300 result = prime * result + *valPtr; 3301 break; 3302 } 3303 case GPBDataTypeSFixed64: 3304 case GPBDataTypeInt64: 3305 case GPBDataTypeSInt64: 3306 case GPBDataTypeFixed64: 3307 case GPBDataTypeUInt64: 3308 case GPBDataTypeDouble: { 3309 GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); 3310 // These are all 64bit, just mix what fits into an NSUInteger in. 3311 uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; 3312 result = prime * result + (NSUInteger)(*valPtr); 3313 break; 3314 } 3315 case GPBDataTypeBytes: 3316 case GPBDataTypeString: { 3317 // Type doesn't matter here, they both implement -hash:. 3318 id *valPtr = (id *)&storage[fieldOffset]; 3319 result = prime * result + [*valPtr hash]; 3320 break; 3321 } 3322 3323 case GPBDataTypeMessage: 3324 case GPBDataTypeGroup: { 3325 GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; 3326 // Could call -hash on the sub message, but that could recurse pretty 3327 // deep; follow the lead of NSArray/NSDictionary and don't really 3328 // recurse for hash, instead use the field number and the descriptor 3329 // of the sub message. Yes, this could suck for a bunch of messages 3330 // where they all only differ in the sub messages, but if you are 3331 // using a message with sub messages for something that needs -hash, 3332 // odds are you are also copying them as keys, and that deep copy 3333 // will also suck. 3334 result = prime * result + GPBFieldNumber(field); 3335 result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; 3336 break; 3337 } 3338 } // switch() 3339 } 3340 } 3341 3342 // Unknowns and extensions are not included. 3343 3344 return result; 3345} 3346 3347#pragma mark - Description Support 3348 3349- (NSString *)description { 3350 NSString *textFormat = GPBTextFormatForMessage(self, @" "); 3351 NSString *description = 3352 [NSString stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat]; 3353 return description; 3354} 3355 3356#if defined(DEBUG) && DEBUG 3357 3358// Xcode 5.1 added support for custom quick look info. 3359// 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 3360- (id)debugQuickLookObject { 3361 return GPBTextFormatForMessage(self, nil); 3362} 3363 3364#endif // DEBUG 3365 3366#pragma mark - SerializedSize 3367 3368- (size_t)serializedSize { 3369 GPBDescriptor *descriptor = [[self class] descriptor]; 3370 size_t result = 0; 3371 3372 // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() 3373 // avoids doing the has check again. 3374 3375 // Fields. 3376 for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { 3377 GPBFieldType fieldType = fieldDescriptor.fieldType; 3378 GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); 3379 3380 // Single Fields 3381 if (fieldType == GPBFieldTypeSingle) { 3382 BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); 3383 if (!selfHas) { 3384 continue; // Nothing to do. 3385 } 3386 3387 uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); 3388 3389 switch (fieldDataType) { 3390#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ 3391 case GPBDataType##NAME: { \ 3392 TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ 3393 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ 3394 break; \ 3395 } 3396#define CASE_SINGLE_OBJECT(NAME) \ 3397 case GPBDataType##NAME: { \ 3398 id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ 3399 result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ 3400 break; \ 3401 } 3402 CASE_SINGLE_POD(Bool, BOOL, Bool) 3403 CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) 3404 CASE_SINGLE_POD(SFixed32, int32_t, Int32) 3405 CASE_SINGLE_POD(Float, float, Float) 3406 CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) 3407 CASE_SINGLE_POD(SFixed64, int64_t, Int64) 3408 CASE_SINGLE_POD(Double, double, Double) 3409 CASE_SINGLE_POD(Int32, int32_t, Int32) 3410 CASE_SINGLE_POD(Int64, int64_t, Int64) 3411 CASE_SINGLE_POD(SInt32, int32_t, Int32) 3412 CASE_SINGLE_POD(SInt64, int64_t, Int64) 3413 CASE_SINGLE_POD(UInt32, uint32_t, UInt32) 3414 CASE_SINGLE_POD(UInt64, uint64_t, UInt64) 3415 CASE_SINGLE_OBJECT(Bytes) 3416 CASE_SINGLE_OBJECT(String) 3417 CASE_SINGLE_OBJECT(Message) 3418 CASE_SINGLE_OBJECT(Group) 3419 CASE_SINGLE_POD(Enum, int32_t, Int32) 3420#undef CASE_SINGLE_POD 3421#undef CASE_SINGLE_OBJECT 3422 } 3423 3424 // Repeated Fields 3425 } else if (fieldType == GPBFieldTypeRepeated) { 3426 id genericArray = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 3427 NSUInteger count = [genericArray count]; 3428 if (count == 0) { 3429 continue; // Nothing to add. 3430 } 3431 __block size_t dataSize = 0; 3432 3433 switch (fieldDataType) { 3434#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) 3435#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ 3436 case GPBDataType##NAME: { \ 3437 GPB##ARRAY_TYPE##Array *array = genericArray; \ 3438 [array enumerate##ARRAY_ACCESSOR_NAME## \ 3439 ValuesWithBlock:^(TYPE value, __unused NSUInteger idx, __unused BOOL * stop) { \ 3440 dataSize += GPBCompute##NAME##SizeNoTag(value); \ 3441 }]; \ 3442 break; \ 3443 } 3444#define CASE_REPEATED_OBJECT(NAME) \ 3445 case GPBDataType##NAME: { \ 3446 for (id value in genericArray) { \ 3447 dataSize += GPBCompute##NAME##SizeNoTag(value); \ 3448 } \ 3449 break; \ 3450 } 3451 CASE_REPEATED_POD(Bool, BOOL, Bool) 3452 CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) 3453 CASE_REPEATED_POD(SFixed32, int32_t, Int32) 3454 CASE_REPEATED_POD(Float, float, Float) 3455 CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) 3456 CASE_REPEATED_POD(SFixed64, int64_t, Int64) 3457 CASE_REPEATED_POD(Double, double, Double) 3458 CASE_REPEATED_POD(Int32, int32_t, Int32) 3459 CASE_REPEATED_POD(Int64, int64_t, Int64) 3460 CASE_REPEATED_POD(SInt32, int32_t, Int32) 3461 CASE_REPEATED_POD(SInt64, int64_t, Int64) 3462 CASE_REPEATED_POD(UInt32, uint32_t, UInt32) 3463 CASE_REPEATED_POD(UInt64, uint64_t, UInt64) 3464 CASE_REPEATED_OBJECT(Bytes) 3465 CASE_REPEATED_OBJECT(String) 3466 CASE_REPEATED_OBJECT(Message) 3467 CASE_REPEATED_OBJECT(Group) 3468 CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) 3469#undef CASE_REPEATED_POD 3470#undef CASE_REPEATED_POD_EXTRA 3471#undef CASE_REPEATED_OBJECT 3472 } // switch 3473 result += dataSize; 3474 size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); 3475 if (fieldDataType == GPBDataTypeGroup) { 3476 // Groups have both a start and an end tag. 3477 tagSize *= 2; 3478 } 3479 if (fieldDescriptor.isPackable) { 3480 result += tagSize; 3481 result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); 3482 } else { 3483 result += count * tagSize; 3484 } 3485 3486 // Map<> Fields 3487 } else { // fieldType == GPBFieldTypeMap 3488 if (GPBDataTypeIsObject(fieldDataType) && 3489 (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { 3490 // If key type was string, then the map is an NSDictionary. 3491 NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 3492 if (map) { 3493 result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); 3494 } 3495 } else { 3496 // Type will be GPB*GroupDictionary, exact type doesn't matter. 3497 GPBInt32Int32Dictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 3498 result += [map computeSerializedSizeAsField:fieldDescriptor]; 3499 } 3500 } 3501 } // for(fields) 3502 3503 // Add any unknown fields. 3504 @synchronized(self) { 3505 if (unknownFieldData_) { 3506#if defined(DEBUG) && DEBUG 3507 NSAssert(unknownFields_ == nil, @"Internal error both unknown states were set"); 3508#endif 3509 result += [unknownFieldData_ length]; 3510 } else { 3511 if (descriptor.wireFormat) { 3512 result += [unknownFields_ serializedSizeAsMessageSet]; 3513 } else { 3514 result += [unknownFields_ serializedSize]; 3515 } 3516 } 3517 } // @synchronized(self) 3518 3519 // Add any extensions. 3520 for (GPBExtensionDescriptor *extension in extensionMap_) { 3521 id value = [extensionMap_ objectForKey:extension]; 3522 result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); 3523 } 3524 3525 return result; 3526} 3527 3528#pragma mark - Resolve Methods Support 3529 3530typedef struct ResolveIvarAccessorMethodResult { 3531 IMP impToAdd; 3532 SEL encodingSelector; 3533} ResolveIvarAccessorMethodResult; 3534 3535// |field| can be __unsafe_unretained because they are created at startup 3536// and are essentially global. No need to pay for retain/release when 3537// they are captured in blocks. 3538static void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, 3539 ResolveIvarAccessorMethodResult *result) { 3540 GPBDataType fieldDataType = GPBGetFieldDataType(field); 3541 switch (fieldDataType) { 3542#define CASE_GET(NAME, TYPE, TRUE_NAME) \ 3543 case GPBDataType##NAME: { \ 3544 result->impToAdd = imp_implementationWithBlock(^(id obj) { \ 3545 return GPBGetMessage##TRUE_NAME##Field(obj, field); \ 3546 }); \ 3547 result->encodingSelector = @selector(get##NAME); \ 3548 break; \ 3549 } 3550#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ 3551 case GPBDataType##NAME: { \ 3552 result->impToAdd = imp_implementationWithBlock(^(id obj) { \ 3553 return GPBGetObjectIvarWithField(obj, field); \ 3554 }); \ 3555 result->encodingSelector = @selector(get##NAME); \ 3556 break; \ 3557 } 3558 CASE_GET(Bool, BOOL, Bool) 3559 CASE_GET(Fixed32, uint32_t, UInt32) 3560 CASE_GET(SFixed32, int32_t, Int32) 3561 CASE_GET(Float, float, Float) 3562 CASE_GET(Fixed64, uint64_t, UInt64) 3563 CASE_GET(SFixed64, int64_t, Int64) 3564 CASE_GET(Double, double, Double) 3565 CASE_GET(Int32, int32_t, Int32) 3566 CASE_GET(Int64, int64_t, Int64) 3567 CASE_GET(SInt32, int32_t, Int32) 3568 CASE_GET(SInt64, int64_t, Int64) 3569 CASE_GET(UInt32, uint32_t, UInt32) 3570 CASE_GET(UInt64, uint64_t, UInt64) 3571 CASE_GET_OBJECT(Bytes, id, Object) 3572 CASE_GET_OBJECT(String, id, Object) 3573 CASE_GET_OBJECT(Message, id, Object) 3574 CASE_GET_OBJECT(Group, id, Object) 3575 CASE_GET(Enum, int32_t, Enum) 3576#undef CASE_GET 3577 } 3578} 3579 3580// See comment about __unsafe_unretained on ResolveIvarGet. 3581static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, 3582 ResolveIvarAccessorMethodResult *result) { 3583 GPBDataType fieldDataType = GPBGetFieldDataType(field); 3584 switch (fieldDataType) { 3585#define CASE_SET(NAME, TYPE, TRUE_NAME) \ 3586 case GPBDataType##NAME: { \ 3587 result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ 3588 return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value); \ 3589 }); \ 3590 result->encodingSelector = @selector(set##NAME:); \ 3591 break; \ 3592 } 3593#define CASE_SET_COPY(NAME) \ 3594 case GPBDataType##NAME: { \ 3595 result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ 3596 return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \ 3597 }); \ 3598 result->encodingSelector = @selector(set##NAME:); \ 3599 break; \ 3600 } 3601 CASE_SET(Bool, BOOL, Bool) 3602 CASE_SET(Fixed32, uint32_t, UInt32) 3603 CASE_SET(SFixed32, int32_t, Int32) 3604 CASE_SET(Float, float, Float) 3605 CASE_SET(Fixed64, uint64_t, UInt64) 3606 CASE_SET(SFixed64, int64_t, Int64) 3607 CASE_SET(Double, double, Double) 3608 CASE_SET(Int32, int32_t, Int32) 3609 CASE_SET(Int64, int64_t, Int64) 3610 CASE_SET(SInt32, int32_t, Int32) 3611 CASE_SET(SInt64, int64_t, Int64) 3612 CASE_SET(UInt32, uint32_t, UInt32) 3613 CASE_SET(UInt64, uint64_t, UInt64) 3614 CASE_SET_COPY(Bytes) 3615 CASE_SET_COPY(String) 3616 CASE_SET(Message, id, Object) 3617 CASE_SET(Group, id, Object) 3618 CASE_SET(Enum, int32_t, Enum) 3619#undef CASE_SET 3620 } 3621} 3622 3623// Highly optimized routines for determining selector types. 3624// Meant to only be used by GPBMessage when resolving selectors in 3625// `+ (BOOL)resolveInstanceMethod:(SEL)sel`. 3626// These routines are intended to make negative decisions as fast as possible. 3627GPB_INLINE char GPBFastToUpper(char c) { return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; } 3628 3629GPB_INLINE BOOL GPBIsGetSelForField(const char *selName, GPBFieldDescriptor *descriptor) { 3630 // Does 'selName' == '<name>'? 3631 // selName and <name> have to be at least two characters long (i.e. ('a', '\0')" is the shortest 3632 // selector you can have). 3633 return (selName[0] == descriptor->description_->name[0]) && 3634 (selName[1] == descriptor->description_->name[1]) && 3635 (strcmp(selName + 1, descriptor->description_->name + 1) == 0); 3636} 3637 3638GPB_INLINE BOOL GPBIsSetSelForField(const char *selName, size_t selNameLength, 3639 GPBFieldDescriptor *descriptor) { 3640 // Does 'selName' == 'set<Name>:'? 3641 // Do fastest compares up front 3642 const size_t kSetLength = strlen("set"); 3643 // kSetLength is 3 and one for the colon. 3644 if (selNameLength <= kSetLength + 1) { 3645 return NO; 3646 } 3647 if (selName[kSetLength] != GPBFastToUpper(descriptor->description_->name[0])) { 3648 return NO; 3649 } 3650 3651 // NB we check for "set" and the colon later in this routine because we have already checked for 3652 // starting with "s" and ending with ":" in `+resolveInstanceMethod:` before we get here. 3653 if (selName[0] != 's' || selName[1] != 'e' || selName[2] != 't') { 3654 return NO; 3655 } 3656 3657 if (selName[selNameLength - 1] != ':') { 3658 return NO; 3659 } 3660 3661 // Slow path. 3662 size_t nameLength = strlen(descriptor->description_->name); 3663 size_t setSelLength = nameLength + kSetLength + 1; 3664 if (selNameLength != setSelLength) { 3665 return NO; 3666 } 3667 if (strncmp(&selName[kSetLength + 1], descriptor->description_->name + 1, nameLength - 1) != 0) { 3668 return NO; 3669 } 3670 3671 return YES; 3672} 3673 3674GPB_INLINE BOOL GPBFieldHasHas(GPBFieldDescriptor *descriptor) { 3675 // It gets has/setHas selectors if... 3676 // - not in a oneof (negative has index) 3677 // - not clearing on zero 3678 return (descriptor->description_->hasIndex >= 0) && 3679 ((descriptor->description_->flags & GPBFieldClearHasIvarOnZero) == 0); 3680} 3681 3682GPB_INLINE BOOL GPBIsHasSelForField(const char *selName, size_t selNameLength, 3683 GPBFieldDescriptor *descriptor) { 3684 // Does 'selName' == 'has<Name>'? 3685 // Do fastest compares up front. 3686 const size_t kHasLength = strlen("has"); 3687 if (selNameLength <= kHasLength) { 3688 return NO; 3689 } 3690 if (selName[0] != 'h' || selName[1] != 'a' || selName[2] != 's') { 3691 return NO; 3692 } 3693 if (selName[kHasLength] != GPBFastToUpper(descriptor->description_->name[0])) { 3694 return NO; 3695 } 3696 if (!GPBFieldHasHas(descriptor)) { 3697 return NO; 3698 } 3699 3700 // Slow path. 3701 size_t nameLength = strlen(descriptor->description_->name); 3702 size_t setSelLength = nameLength + kHasLength; 3703 if (selNameLength != setSelLength) { 3704 return NO; 3705 } 3706 3707 if (strncmp(&selName[kHasLength + 1], descriptor->description_->name + 1, nameLength - 1) != 0) { 3708 return NO; 3709 } 3710 return YES; 3711} 3712 3713GPB_INLINE BOOL GPBIsCountSelForField(const char *selName, size_t selNameLength, 3714 GPBFieldDescriptor *descriptor) { 3715 // Does 'selName' == '<name>_Count'? 3716 // Do fastest compares up front. 3717 if (selName[0] != descriptor->description_->name[0]) { 3718 return NO; 3719 } 3720 const size_t kCountLength = strlen("_Count"); 3721 if (selNameLength <= kCountLength) { 3722 return NO; 3723 } 3724 3725 if (selName[selNameLength - kCountLength] != '_') { 3726 return NO; 3727 } 3728 3729 // Slow path. 3730 size_t nameLength = strlen(descriptor->description_->name); 3731 size_t setSelLength = nameLength + kCountLength; 3732 if (selNameLength != setSelLength) { 3733 return NO; 3734 } 3735 if (strncmp(selName, descriptor->description_->name, nameLength) != 0) { 3736 return NO; 3737 } 3738 if (strncmp(&selName[nameLength], "_Count", kCountLength) != 0) { 3739 return NO; 3740 } 3741 return YES; 3742} 3743 3744GPB_INLINE BOOL GPBIsSetHasSelForField(const char *selName, size_t selNameLength, 3745 GPBFieldDescriptor *descriptor) { 3746 // Does 'selName' == 'setHas<Name>:'? 3747 // Do fastest compares up front. 3748 const size_t kSetHasLength = strlen("setHas"); 3749 // kSetHasLength is 6 and one for the colon. 3750 if (selNameLength <= kSetHasLength + 1) { 3751 return NO; 3752 } 3753 if (selName[selNameLength - 1] != ':') { 3754 return NO; 3755 } 3756 if (selName[kSetHasLength] != GPBFastToUpper(descriptor->description_->name[0])) { 3757 return NO; 3758 } 3759 if (selName[0] != 's' || selName[1] != 'e' || selName[2] != 't' || selName[3] != 'H' || 3760 selName[4] != 'a' || selName[5] != 's') { 3761 return NO; 3762 } 3763 3764 if (!GPBFieldHasHas(descriptor)) { 3765 return NO; 3766 } 3767 // Slow path. 3768 size_t nameLength = strlen(descriptor->description_->name); 3769 size_t setHasSelLength = nameLength + kSetHasLength + 1; 3770 if (selNameLength != setHasSelLength) { 3771 return NO; 3772 } 3773 if (strncmp(&selName[kSetHasLength + 1], descriptor->description_->name + 1, nameLength - 1) != 3774 0) { 3775 return NO; 3776 } 3777 3778 return YES; 3779} 3780 3781GPB_INLINE BOOL GPBIsCaseOfSelForOneOf(const char *selName, size_t selNameLength, 3782 GPBOneofDescriptor *descriptor) { 3783 // Does 'selName' == '<name>OneOfCase'? 3784 // Do fastest compares up front. 3785 if (selName[0] != descriptor->name_[0]) { 3786 return NO; 3787 } 3788 const size_t kOneOfCaseLength = strlen("OneOfCase"); 3789 if (selNameLength <= kOneOfCaseLength) { 3790 return NO; 3791 } 3792 if (selName[selNameLength - kOneOfCaseLength] != 'O') { 3793 return NO; 3794 } 3795 3796 // Slow path. 3797 size_t nameLength = strlen(descriptor->name_); 3798 size_t setSelLength = nameLength + kOneOfCaseLength; 3799 if (selNameLength != setSelLength) { 3800 return NO; 3801 } 3802 if (strncmp(&selName[nameLength], "OneOfCase", kOneOfCaseLength) != 0) { 3803 return NO; 3804 } 3805 if (strncmp(selName, descriptor->name_, nameLength) != 0) { 3806 return NO; 3807 } 3808 return YES; 3809} 3810 3811+ (BOOL)resolveInstanceMethod:(SEL)sel { 3812 const GPBDescriptor *descriptor = [self descriptor]; 3813 if (!descriptor) { 3814 return [super resolveInstanceMethod:sel]; 3815 } 3816 ResolveIvarAccessorMethodResult result = {NULL, NULL}; 3817 3818 const char *selName = sel_getName(sel); 3819 const size_t selNameLength = strlen(selName); 3820 // A setter has a leading 's' and a trailing ':' (e.g. 'setFoo:' or 'setHasFoo:'). 3821 BOOL couldBeSetter = selName[0] == 's' && selName[selNameLength - 1] == ':'; 3822 if (couldBeSetter) { 3823 // See comment about __unsafe_unretained on ResolveIvarGet. 3824 for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { 3825 BOOL isMapOrArray = GPBFieldIsMapOrArray(field); 3826 if (GPBIsSetSelForField(selName, selNameLength, field)) { 3827 if (isMapOrArray) { 3828 // Local for syntax so the block can directly capture it and not the 3829 // full lookup. 3830 result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { 3831 GPBSetObjectIvarWithFieldPrivate(obj, field, value); 3832 }); 3833 result.encodingSelector = @selector(setArray:); 3834 } else { 3835 ResolveIvarSet(field, &result); 3836 } 3837 break; 3838 } else if (!isMapOrArray && GPBIsSetHasSelForField(selName, selNameLength, field)) { 3839 result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { 3840 if (value) { 3841 [NSException raise:NSInvalidArgumentException 3842 format:@"%@: %@ can only be set to NO (to clear field).", [obj class], 3843 NSStringFromSelector(sel)]; 3844 } 3845 GPBClearMessageField(obj, field); 3846 }); 3847 result.encodingSelector = @selector(setBool:); 3848 break; 3849 } 3850 } 3851 } else { 3852 // See comment about __unsafe_unretained on ResolveIvarGet. 3853 for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { 3854 BOOL isMapOrArray = GPBFieldIsMapOrArray(field); 3855 if (GPBIsGetSelForField(selName, field)) { 3856 if (isMapOrArray) { 3857 if (field.fieldType == GPBFieldTypeRepeated) { 3858 result.impToAdd = imp_implementationWithBlock(^(id obj) { 3859 return GetArrayIvarWithField(obj, field); 3860 }); 3861 } else { 3862 result.impToAdd = imp_implementationWithBlock(^(id obj) { 3863 return GetMapIvarWithField(obj, field); 3864 }); 3865 } 3866 result.encodingSelector = @selector(getArray); 3867 } else { 3868 ResolveIvarGet(field, &result); 3869 } 3870 break; 3871 } 3872 if (!isMapOrArray) { 3873 if (GPBIsHasSelForField(selName, selNameLength, field)) { 3874 int32_t index = GPBFieldHasIndex(field); 3875 uint32_t fieldNum = GPBFieldNumber(field); 3876 result.impToAdd = imp_implementationWithBlock(^(id obj) { 3877 return GPBGetHasIvar(obj, index, fieldNum); 3878 }); 3879 result.encodingSelector = @selector(getBool); 3880 break; 3881 } else { 3882 GPBOneofDescriptor *oneof = field->containingOneof_; 3883 if (oneof && GPBIsCaseOfSelForOneOf(selName, selNameLength, oneof)) { 3884 int32_t index = GPBFieldHasIndex(field); 3885 result.impToAdd = imp_implementationWithBlock(^(id obj) { 3886 return GPBGetHasOneof(obj, index); 3887 }); 3888 result.encodingSelector = @selector(getEnum); 3889 break; 3890 } 3891 } 3892 } else { 3893 if (GPBIsCountSelForField(selName, selNameLength, field)) { 3894 result.impToAdd = imp_implementationWithBlock(^(id obj) { 3895 // Type doesn't matter, all *Array and *Dictionary types support 3896 // -count. 3897 NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(obj, field); 3898 return [arrayOrMap count]; 3899 }); 3900 result.encodingSelector = @selector(getArrayCount); 3901 break; 3902 } 3903 } 3904 } 3905 } 3906 3907 if (result.impToAdd) { 3908 const char *encoding = GPBMessageEncodingForSelector(result.encodingSelector, YES); 3909 Class msgClass = descriptor.messageClass; 3910 BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding); 3911 // class_addMethod() is documented as also failing if the method was already 3912 // added; so we check if the method is already there and return success so 3913 // the method dispatch will still happen. Why would it already be added? 3914 // Two threads could cause the same method to be bound at the same time, 3915 // but only one will actually bind it; the other still needs to return true 3916 // so things will dispatch. 3917 if (!methodAdded) { 3918 methodAdded = GPBClassHasSel(msgClass, sel); 3919 } 3920 return methodAdded; 3921 } 3922 return [super resolveInstanceMethod:sel]; 3923} 3924 3925+ (BOOL)resolveClassMethod:(SEL)sel { 3926 // Extensions scoped to a Message and looked up via class methods. 3927 if (GPBResolveExtensionClassMethod(self, sel)) { 3928 return YES; 3929 } 3930 return [super resolveClassMethod:sel]; 3931} 3932 3933#pragma mark - NSCoding Support 3934 3935+ (BOOL)supportsSecureCoding { 3936 return YES; 3937} 3938 3939- (instancetype)initWithCoder:(NSCoder *)aDecoder { 3940 self = [self init]; 3941 if (self) { 3942 NSData *data = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; 3943 if (data.length) { 3944 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 3945 @try { 3946 [self mergeFromCodedInputStream:input extensionRegistry:nil endingTag:0]; 3947 } @finally { 3948 [input release]; 3949 } 3950 } 3951 } 3952 return self; 3953} 3954 3955- (void)encodeWithCoder:(NSCoder *)aCoder { 3956#if defined(DEBUG) && DEBUG 3957 if (extensionMap_.count) { 3958 // Hint to go along with the docs on GPBMessage about this. 3959 // 3960 // Note: This is incomplete, in that it only checked the "root" message, 3961 // if a sub message in a field has extensions, the issue still exists. A 3962 // recursive check could be done here (like the work in 3963 // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to 3964 // be expensive and could slow down serialization in DEBUG enough to cause 3965 // developers other problems. 3966 NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" 3967 @" has %ld extensions; when read back in, those fields will be" 3968 @" in the unknownFields property instead.", 3969 [self class], (long)extensionMap_.count); 3970 } 3971#endif 3972 NSData *data = [self data]; 3973 if (data.length) { 3974 [aCoder encodeObject:data forKey:kGPBDataCoderKey]; 3975 } 3976} 3977 3978#pragma mark - KVC Support 3979 3980+ (BOOL)accessInstanceVariablesDirectly { 3981 // Make sure KVC doesn't use instance variables. 3982 return NO; 3983} 3984 3985@end 3986 3987#pragma mark - Messages from GPBUtilities.h but defined here for access to helpers. 3988 3989// Only exists for public api, no core code should use this. 3990id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { 3991#if defined(DEBUG) && DEBUG 3992 if (field.fieldType != GPBFieldTypeRepeated) { 3993 [NSException raise:NSInvalidArgumentException 3994 format:@"%@.%@ is not a repeated field.", [self class], field.name]; 3995 } 3996#endif 3997 return GetOrCreateArrayIvarWithField(self, field); 3998} 3999 4000// Only exists for public api, no core code should use this. 4001id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { 4002#if defined(DEBUG) && DEBUG 4003 if (field.fieldType != GPBFieldTypeMap) { 4004 [NSException raise:NSInvalidArgumentException 4005 format:@"%@.%@ is not a map<> field.", [self class], field.name]; 4006 } 4007#endif 4008 return GetOrCreateMapIvarWithField(self, field); 4009} 4010 4011id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 4012 NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); 4013 if (!GPBFieldDataTypeIsMessage(field)) { 4014 if (GPBGetHasIvarField(self, field)) { 4015 uint8_t *storage = (uint8_t *)self->messageStorage_; 4016 id *typePtr = (id *)&storage[field->description_->offset]; 4017 return *typePtr; 4018 } 4019 // Not set...non messages (string/data), get their default. 4020 return field.defaultValue.valueMessage; 4021 } 4022 4023 uint8_t *storage = (uint8_t *)self->messageStorage_; 4024 _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 4025 id msg = atomic_load(typePtr); 4026 if (msg) { 4027 return msg; 4028 } 4029 4030 id expected = nil; 4031 id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field); 4032 if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 4033 // Value was set, return it. 4034 return autocreated; 4035 } 4036 4037 // Some other thread set it, release the one created and return what got set. 4038 GPBClearMessageAutocreator(autocreated); 4039 [autocreated release]; 4040 return expected; 4041} 4042 4043NSData *GPBMessageUnknownFieldsData(GPBMessage *self) { 4044 NSData *result = nil; 4045 @synchronized(self) { 4046#pragma clang diagnostic push 4047#pragma clang diagnostic ignored "-Wdeprecated-declarations" 4048 GPBUnknownFieldSet *unknownFields = self->unknownFields_; 4049#pragma clang diagnostic pop 4050 if (unknownFields) { 4051#if defined(DEBUG) && DEBUG 4052 NSCAssert(self->unknownFieldData_ == nil, @"Internal error both unknown states were set"); 4053#endif 4054 if (self.descriptor.isWireFormat) { 4055 NSMutableData *mutableData = 4056 [NSMutableData dataWithLength:unknownFields.serializedSizeAsMessageSet]; 4057 GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:mutableData]; 4058 [unknownFields writeAsMessageSetTo:output]; 4059 [output flush]; 4060 [output release]; 4061 result = mutableData; 4062 } else { 4063 result = [unknownFields data]; 4064 } 4065 } else { 4066 // Internally we can borrow it without a copy since this is immediately used by callers 4067 // and multithreaded access with any mutation is not allow on messages. 4068 result = self->unknownFieldData_; 4069 } 4070 } // @synchronized(self) 4071 return result; 4072} 4073 4074#pragma clang diagnostic pop 4075