1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#import "GPBUtilities_PackagePrivate.h" 32 33#import <objc/runtime.h> 34 35#import "GPBArray_PackagePrivate.h" 36#import "GPBDescriptor_PackagePrivate.h" 37#import "GPBDictionary_PackagePrivate.h" 38#import "GPBMessage_PackagePrivate.h" 39#import "GPBUnknownField.h" 40#import "GPBUnknownFieldSet.h" 41 42// Direct access is use for speed, to avoid even internally declaring things 43// read/write, etc. The warning is enabled in the project to ensure code calling 44// protos can turn on -Wdirect-ivar-access without issues. 45#pragma clang diagnostic push 46#pragma clang diagnostic ignored "-Wdirect-ivar-access" 47 48static void AppendTextFormatForMessage(GPBMessage *message, 49 NSMutableString *toStr, 50 NSString *lineIndent); 51 52// Are two datatypes the same basic type representation (ex Int32 and SInt32). 53// Marked unused because currently only called from asserts/debug. 54static BOOL DataTypesEquivalent(GPBDataType type1, 55 GPBDataType type2) __attribute__ ((unused)); 56 57// Basic type representation for a type (ex: for SInt32 it is Int32). 58// Marked unused because currently only called from asserts/debug. 59static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); 60 61// String name for a data type. 62// Marked unused because currently only called from asserts/debug. 63static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); 64 65NSData *GPBEmptyNSData(void) { 66 static dispatch_once_t onceToken; 67 static NSData *defaultNSData = nil; 68 dispatch_once(&onceToken, ^{ 69 defaultNSData = [[NSData alloc] init]; 70 }); 71 return defaultNSData; 72} 73 74void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) { 75 if (!initialMessage) { 76 return; 77 } 78 79 // Use an array as a list to process to avoid recursion. 80 NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage]; 81 82 while (todo.count) { 83 GPBMessage *msg = todo.lastObject; 84 [todo removeLastObject]; 85 86 // Clear unknowns. 87 msg.unknownFields = nil; 88 89 // Handle the message fields. 90 GPBDescriptor *descriptor = [[msg class] descriptor]; 91 for (GPBFieldDescriptor *field in descriptor->fields_) { 92 if (!GPBFieldDataTypeIsMessage(field)) { 93 continue; 94 } 95 switch (field.fieldType) { 96 case GPBFieldTypeSingle: 97 if (GPBGetHasIvarField(msg, field)) { 98 GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); 99 [todo addObject:fieldMessage]; 100 } 101 break; 102 103 case GPBFieldTypeRepeated: { 104 NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); 105 if (fieldMessages.count) { 106 [todo addObjectsFromArray:fieldMessages]; 107 } 108 break; 109 } 110 111 case GPBFieldTypeMap: { 112 id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field); 113 switch (field.mapKeyDataType) { 114 case GPBDataTypeBool: 115 [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 116 BOOL key, id _Nonnull object, BOOL * _Nonnull stop) { 117 #pragma unused(key, stop) 118 [todo addObject:object]; 119 }]; 120 break; 121 case GPBDataTypeFixed32: 122 case GPBDataTypeUInt32: 123 [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 124 uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) { 125 #pragma unused(key, stop) 126 [todo addObject:object]; 127 }]; 128 break; 129 case GPBDataTypeInt32: 130 case GPBDataTypeSFixed32: 131 case GPBDataTypeSInt32: 132 [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 133 int32_t key, id _Nonnull object, BOOL * _Nonnull stop) { 134 #pragma unused(key, stop) 135 [todo addObject:object]; 136 }]; 137 break; 138 case GPBDataTypeFixed64: 139 case GPBDataTypeUInt64: 140 [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 141 uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) { 142 #pragma unused(key, stop) 143 [todo addObject:object]; 144 }]; 145 break; 146 case GPBDataTypeInt64: 147 case GPBDataTypeSFixed64: 148 case GPBDataTypeSInt64: 149 [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 150 int64_t key, id _Nonnull object, BOOL * _Nonnull stop) { 151 #pragma unused(key, stop) 152 [todo addObject:object]; 153 }]; 154 break; 155 case GPBDataTypeString: 156 [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^( 157 NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) { 158 #pragma unused(key, stop) 159 [todo addObject:obj]; 160 }]; 161 break; 162 case GPBDataTypeFloat: 163 case GPBDataTypeDouble: 164 case GPBDataTypeEnum: 165 case GPBDataTypeBytes: 166 case GPBDataTypeGroup: 167 case GPBDataTypeMessage: 168 NSCAssert(NO, @"Aren't valid key types."); 169 } 170 break; 171 } // switch(field.mapKeyDataType) 172 } // switch(field.fieldType) 173 } // for(fields) 174 175 // Handle any extensions holding messages. 176 for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) { 177 if (!GPBDataTypeIsMessage(extension.dataType)) { 178 continue; 179 } 180 if (extension.isRepeated) { 181 NSArray *extMessages = [msg getExtension:extension]; 182 [todo addObjectsFromArray:extMessages]; 183 } else { 184 GPBMessage *extMessage = [msg getExtension:extension]; 185 [todo addObject:extMessage]; 186 } 187 } // for(extensionsCurrentlySet) 188 189 } // while(todo.count) 190} 191 192 193// -- About Version Checks -- 194// There's actually 3 places these checks all come into play: 195// 1. When the generated source is compile into .o files, the header check 196// happens. This is checking the protoc used matches the library being used 197// when making the .o. 198// 2. Every place a generated proto header is included in a developer's code, 199// the header check comes into play again. But this time it is checking that 200// the current library headers being used still support/match the ones for 201// the generated code. 202// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is 203// called from the generated code passing in values captured when the 204// generated code's .o was made. This checks that at runtime the generated 205// code and runtime library match. 206 207void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) { 208 // NOTE: This is passing the value captured in the compiled code to check 209 // against the values captured when the runtime support was compiled. This 210 // ensures the library code isn't in a different framework/library that 211 // was generated with a non matching version. 212 if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) { 213 // Library is too old for headers. 214 [NSException raise:NSInternalInconsistencyException 215 format:@"Linked to ProtocolBuffer runtime version %d," 216 @" but code compiled needing atleast %d!", 217 GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion]; 218 } 219 if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { 220 // Headers are too old for library. 221 [NSException raise:NSInternalInconsistencyException 222 format:@"Proto generation source compiled against runtime" 223 @" version %d, but this version of the runtime only" 224 @" supports back to %d!", 225 objcRuntimeVersion, 226 GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION]; 227 } 228} 229 230// This api is no longer used for version checks. 30001 is the last version 231// using this old versioning model. When that support is removed, this function 232// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h). 233void GPBCheckRuntimeVersionInternal(int32_t version) { 234 GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001, 235 time_to_remove_this_old_version_shim); 236 if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { 237 [NSException raise:NSInternalInconsistencyException 238 format:@"Linked to ProtocolBuffer runtime version %d," 239 @" but code compiled with version %d!", 240 GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; 241 } 242} 243 244BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { 245 GPBDescriptor *descriptor = [self descriptor]; 246 GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; 247 return GPBMessageHasFieldSet(self, field); 248} 249 250BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) { 251 if (self == nil || field == nil) return NO; 252 253 // Repeated/Map don't use the bit, they check the count. 254 if (GPBFieldIsMapOrArray(field)) { 255 // Array/map type doesn't matter, since GPB*Array/NSArray and 256 // GPB*Dictionary/NSDictionary all support -count; 257 NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 258 return (arrayOrMap.count > 0); 259 } else { 260 return GPBGetHasIvarField(self, field); 261 } 262} 263 264void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { 265 // If not set, nothing to do. 266 if (!GPBGetHasIvarField(self, field)) { 267 return; 268 } 269 270 if (GPBFieldStoresObject(field)) { 271 // Object types are handled slightly differently, they need to be released. 272 uint8_t *storage = (uint8_t *)self->messageStorage_; 273 id *typePtr = (id *)&storage[field->description_->offset]; 274 [*typePtr release]; 275 *typePtr = nil; 276 } else { 277 // POD types just need to clear the has bit as the Get* method will 278 // fetch the default when needed. 279 } 280 GPBSetHasIvarField(self, field, NO); 281} 282 283BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { 284 NSCAssert(self->messageStorage_ != NULL, 285 @"%@: All messages should have storage (from init)", 286 [self class]); 287 if (idx < 0) { 288 NSCAssert(fieldNumber != 0, @"Invalid field number."); 289 BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber); 290 return hasIvar; 291 } else { 292 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); 293 uint32_t byteIndex = idx / 32; 294 uint32_t bitMask = (1U << (idx % 32)); 295 BOOL hasIvar = 296 (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO; 297 return hasIvar; 298 } 299} 300 301uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) { 302 NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", 303 [self class], idx); 304 uint32_t result = self->messageStorage_->_has_storage_[-idx]; 305 return result; 306} 307 308void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, 309 BOOL value) { 310 if (idx < 0) { 311 NSCAssert(fieldNumber != 0, @"Invalid field number."); 312 uint32_t *has_storage = self->messageStorage_->_has_storage_; 313 has_storage[-idx] = (value ? fieldNumber : 0); 314 } else { 315 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); 316 uint32_t *has_storage = self->messageStorage_->_has_storage_; 317 uint32_t byte = idx / 32; 318 uint32_t bitMask = (1U << (idx % 32)); 319 if (value) { 320 has_storage[byte] |= bitMask; 321 } else { 322 has_storage[byte] &= ~bitMask; 323 } 324 } 325} 326 327void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, 328 int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { 329 uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); 330 if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { 331 // Do nothing/nothing set in the oneof. 332 return; 333 } 334 335 // Like GPBClearMessageField(), free the memory if an objecttype is set, 336 // pod types don't need to do anything. 337 GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet]; 338 NSCAssert(fieldSet, 339 @"%@: oneof set to something (%u) not in the oneof?", 340 [self class], fieldNumberSet); 341 if (fieldSet && GPBFieldStoresObject(fieldSet)) { 342 uint8_t *storage = (uint8_t *)self->messageStorage_; 343 id *typePtr = (id *)&storage[fieldSet->description_->offset]; 344 [*typePtr release]; 345 *typePtr = nil; 346 } 347 348 // Set to nothing stored in the oneof. 349 // (field number doesn't matter since setting to nothing). 350 GPBSetHasIvar(self, oneofHasIndex, 1, NO); 351} 352 353#pragma mark - IVar accessors 354 355//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) 356//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, 357//% TYPE$S NAME$S GPBFieldDescriptor *field) { 358//%#if defined(DEBUG) && DEBUG 359//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 360//% GPBDataType##NAME), 361//% @"Attempting to get value of TYPE from field %@ " 362//% @"of %@ which is of type %@.", 363//% [self class], field.name, 364//% TypeToString(GPBGetFieldDataType(field))); 365//%#endif 366//% if (GPBGetHasIvarField(self, field)) { 367//% uint8_t *storage = (uint8_t *)self->messageStorage_; 368//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; 369//% return *typePtr; 370//% } else { 371//% return field.defaultValue.value##NAME; 372//% } 373//%} 374//% 375//%// Only exists for public api, no core code should use this. 376//%void GPBSetMessage##NAME##Field(GPBMessage *self, 377//% NAME$S GPBFieldDescriptor *field, 378//% NAME$S TYPE value) { 379//% if (self == nil || field == nil) return; 380//% GPBFileSyntax syntax = [self descriptor].file.syntax; 381//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); 382//%} 383//% 384//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, 385//% NAME$S GPBFieldDescriptor *field, 386//% NAME$S TYPE value, 387//% NAME$S GPBFileSyntax syntax) { 388//%#if defined(DEBUG) && DEBUG 389//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 390//% GPBDataType##NAME), 391//% @"Attempting to set field %@ of %@ which is of type %@ with " 392//% @"value of type TYPE.", 393//% [self class], field.name, 394//% TypeToString(GPBGetFieldDataType(field))); 395//%#endif 396//% GPBOneofDescriptor *oneof = field->containingOneof_; 397//% if (oneof) { 398//% GPBMessageFieldDescription *fieldDesc = field->description_; 399//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 400//% } 401//%#if defined(DEBUG) && DEBUG 402//% NSCAssert(self->messageStorage_ != NULL, 403//% @"%@: All messages should have storage (from init)", 404//% [self class]); 405//%#endif 406//%#if defined(__clang_analyzer__) 407//% if (self->messageStorage_ == NULL) return; 408//%#endif 409//% uint8_t *storage = (uint8_t *)self->messageStorage_; 410//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; 411//% *typePtr = value; 412//% // proto2: any value counts as having been set; proto3, it 413//% // has to be a non zero value or be in a oneof. 414//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 415//% || (value != (TYPE)0) 416//% || (field->containingOneof_ != NULL)); 417//% GPBSetHasIvarField(self, field, hasValue); 418//% GPBBecomeVisibleToAutocreator(self); 419//%} 420//% 421//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE) 422//%// Only exists for public api, no core code should use this. 423//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, 424//% TYPE$S NAME$S GPBFieldDescriptor *field) { 425//%#if defined(DEBUG) && DEBUG 426//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 427//% GPBDataType##NAME), 428//% @"Attempting to get value of TYPE from field %@ " 429//% @"of %@ which is of type %@.", 430//% [self class], field.name, 431//% TypeToString(GPBGetFieldDataType(field))); 432//%#endif 433//% return (TYPE *)GPBGetObjectIvarWithField(self, field); 434//%} 435//% 436//%// Only exists for public api, no core code should use this. 437//%void GPBSetMessage##NAME##Field(GPBMessage *self, 438//% NAME$S GPBFieldDescriptor *field, 439//% NAME$S TYPE *value) { 440//%#if defined(DEBUG) && DEBUG 441//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 442//% GPBDataType##NAME), 443//% @"Attempting to set field %@ of %@ which is of type %@ with " 444//% @"value of type TYPE.", 445//% [self class], field.name, 446//% TypeToString(GPBGetFieldDataType(field))); 447//%#endif 448//% GPBSetObjectIvarWithField(self, field, (id)value); 449//%} 450//% 451//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE) 452//%// Only exists for public api, no core code should use this. 453//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, 454//% TYPE$S NAME$S GPBFieldDescriptor *field) { 455//%#if defined(DEBUG) && DEBUG 456//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 457//% GPBDataType##NAME), 458//% @"Attempting to get value of TYPE from field %@ " 459//% @"of %@ which is of type %@.", 460//% [self class], field.name, 461//% TypeToString(GPBGetFieldDataType(field))); 462//%#endif 463//% return (TYPE *)GPBGetObjectIvarWithField(self, field); 464//%} 465//% 466//%// Only exists for public api, no core code should use this. 467//%void GPBSetMessage##NAME##Field(GPBMessage *self, 468//% NAME$S GPBFieldDescriptor *field, 469//% NAME$S TYPE *value) { 470//%#if defined(DEBUG) && DEBUG 471//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 472//% GPBDataType##NAME), 473//% @"Attempting to set field %@ of %@ which is of type %@ with " 474//% @"value of type TYPE.", 475//% [self class], field.name, 476//% TypeToString(GPBGetFieldDataType(field))); 477//%#endif 478//% GPBSetCopyObjectIvarWithField(self, field, (id)value); 479//%} 480//% 481 482// Object types are handled slightly differently, they need to be released 483// and retained. 484 485void GPBSetAutocreatedRetainedObjectIvarWithField( 486 GPBMessage *self, GPBFieldDescriptor *field, 487 id __attribute__((ns_consumed)) value) { 488 uint8_t *storage = (uint8_t *)self->messageStorage_; 489 id *typePtr = (id *)&storage[field->description_->offset]; 490 NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); 491 *typePtr = value; 492} 493 494void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, 495 GPBFieldDescriptor *field) { 496 if (GPBGetHasIvarField(self, field)) { 497 return; 498 } 499 uint8_t *storage = (uint8_t *)self->messageStorage_; 500 id *typePtr = (id *)&storage[field->description_->offset]; 501 GPBMessage *oldValue = *typePtr; 502 *typePtr = NULL; 503 GPBClearMessageAutocreator(oldValue); 504 [oldValue release]; 505} 506 507// This exists only for briging some aliased types, nothing else should use it. 508static void GPBSetObjectIvarWithField(GPBMessage *self, 509 GPBFieldDescriptor *field, id value) { 510 if (self == nil || field == nil) return; 511 GPBFileSyntax syntax = [self descriptor].file.syntax; 512 GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], 513 syntax); 514} 515 516static void GPBSetCopyObjectIvarWithField(GPBMessage *self, 517 GPBFieldDescriptor *field, id value); 518 519// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags 520// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldInternal 521// is marked as consuming the value. Note: For some reason this doesn't happen 522// with the -retain in GPBSetObjectIvarWithField. 523#if !defined(__clang_analyzer__) 524// This exists only for briging some aliased types, nothing else should use it. 525static void GPBSetCopyObjectIvarWithField(GPBMessage *self, 526 GPBFieldDescriptor *field, id value) { 527 if (self == nil || field == nil) return; 528 GPBFileSyntax syntax = [self descriptor].file.syntax; 529 GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value copy], 530 syntax); 531} 532#endif // !defined(__clang_analyzer__) 533 534void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, 535 GPBFieldDescriptor *field, id value, 536 GPBFileSyntax syntax) { 537 GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], 538 syntax); 539} 540 541void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, 542 GPBFieldDescriptor *field, 543 id value, GPBFileSyntax syntax) { 544 NSCAssert(self->messageStorage_ != NULL, 545 @"%@: All messages should have storage (from init)", 546 [self class]); 547#if defined(__clang_analyzer__) 548 if (self->messageStorage_ == NULL) return; 549#endif 550 GPBDataType fieldType = GPBGetFieldDataType(field); 551 BOOL isMapOrArray = GPBFieldIsMapOrArray(field); 552 BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); 553#if defined(DEBUG) && DEBUG 554 if (value == nil && !isMapOrArray && !fieldIsMessage && 555 field.hasDefaultValue) { 556 // Setting a message to nil is an obvious way to "clear" the value 557 // as there is no way to set a non-empty default value for messages. 558 // 559 // For Strings and Bytes that have default values set it is not clear what 560 // should be done when their value is set to nil. Is the intention just to 561 // clear the set value and reset to default, or is the intention to set the 562 // value to the empty string/data? Arguments can be made for both cases. 563 // 'nil' has been abused as a replacement for an empty string/data in ObjC. 564 // We decided to be consistent with all "object" types and clear the has 565 // field, and fall back on the default value. The warning below will only 566 // appear in debug, but the could should be changed so the intention is 567 // clear. 568 NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_); 569 NSString *propName = field.name; 570 NSString *className = self.descriptor.name; 571 NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " 572 @"default values. Please use '%@.%@ = %@' if you want to set it to " 573 @"empty, or call '%@.%@ = NO' to reset it to it's default value of " 574 @"'%@'. Defaulting to resetting default value.", 575 className, propName, className, propName, 576 (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", 577 className, hasSel, field.defaultValue.valueString); 578 // Note: valueString, depending on the type, it could easily be 579 // valueData/valueMessage. 580 } 581#endif // DEBUG 582 if (!isMapOrArray) { 583 // Non repeated/map can be in an oneof, clear any existing value from the 584 // oneof. 585 GPBOneofDescriptor *oneof = field->containingOneof_; 586 if (oneof) { 587 GPBMessageFieldDescription *fieldDesc = field->description_; 588 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 589 } 590 // Clear "has" if they are being set to nil. 591 BOOL setHasValue = (value != nil); 592 // Under proto3, Bytes & String fields get cleared by resetting them to 593 // their default (empty) values, so if they are set to something of length 594 // zero, they are being cleared. 595 if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && 596 ([value length] == 0)) { 597 // Except, if the field was in a oneof, then it still gets recorded as 598 // having been set so the state of the oneof can be serialized back out. 599 if (!oneof) { 600 setHasValue = NO; 601 } 602 if (setHasValue) { 603 NSCAssert(value != nil, @"Should never be setting has for nil"); 604 } else { 605 // The value passed in was retained, it must be released since we 606 // aren't saving anything in the field. 607 [value release]; 608 value = nil; 609 } 610 } 611 GPBSetHasIvarField(self, field, setHasValue); 612 } 613 uint8_t *storage = (uint8_t *)self->messageStorage_; 614 id *typePtr = (id *)&storage[field->description_->offset]; 615 616 id oldValue = *typePtr; 617 618 *typePtr = value; 619 620 if (oldValue) { 621 if (isMapOrArray) { 622 if (field.fieldType == GPBFieldTypeRepeated) { 623 // If the old array was autocreated by us, then clear it. 624 if (GPBDataTypeIsObject(fieldType)) { 625 if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) { 626 GPBAutocreatedArray *autoArray = oldValue; 627 if (autoArray->_autocreator == self) { 628 autoArray->_autocreator = nil; 629 } 630 } 631 } else { 632 // Type doesn't matter, it is a GPB*Array. 633 GPBInt32Array *gpbArray = oldValue; 634 if (gpbArray->_autocreator == self) { 635 gpbArray->_autocreator = nil; 636 } 637 } 638 } else { // GPBFieldTypeMap 639 // If the old map was autocreated by us, then clear it. 640 if ((field.mapKeyDataType == GPBDataTypeString) && 641 GPBDataTypeIsObject(fieldType)) { 642 if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) { 643 GPBAutocreatedDictionary *autoDict = oldValue; 644 if (autoDict->_autocreator == self) { 645 autoDict->_autocreator = nil; 646 } 647 } 648 } else { 649 // Type doesn't matter, it is a GPB*Dictionary. 650 GPBInt32Int32Dictionary *gpbDict = oldValue; 651 if (gpbDict->_autocreator == self) { 652 gpbDict->_autocreator = nil; 653 } 654 } 655 } 656 } else if (fieldIsMessage) { 657 // If the old message value was autocreated by us, then clear it. 658 GPBMessage *oldMessageValue = oldValue; 659 if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) { 660 GPBClearMessageAutocreator(oldMessageValue); 661 } 662 } 663 [oldValue release]; 664 } 665 666 GPBBecomeVisibleToAutocreator(self); 667} 668 669id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, 670 GPBFieldDescriptor *field) { 671 if (self->messageStorage_ == nil) { 672 return nil; 673 } 674 uint8_t *storage = (uint8_t *)self->messageStorage_; 675 id *typePtr = (id *)&storage[field->description_->offset]; 676 return *typePtr; 677} 678 679// Only exists for public api, no core code should use this. 680int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { 681 GPBFileSyntax syntax = [self descriptor].file.syntax; 682 return GPBGetEnumIvarWithFieldInternal(self, field, syntax); 683} 684 685int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, 686 GPBFieldDescriptor *field, 687 GPBFileSyntax syntax) { 688#if defined(DEBUG) && DEBUG 689 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, 690 @"Attempting to get value of type Enum from field %@ " 691 @"of %@ which is of type %@.", 692 [self class], field.name, 693 TypeToString(GPBGetFieldDataType(field))); 694#endif 695 int32_t result = GPBGetMessageInt32Field(self, field); 696 // If this is presevering unknown enums, make sure the value is valid before 697 // returning it. 698 if (GPBHasPreservingUnknownEnumSemantics(syntax) && 699 ![field isValidEnumValue:result]) { 700 result = kGPBUnrecognizedEnumeratorValue; 701 } 702 return result; 703} 704 705// Only exists for public api, no core code should use this. 706void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, 707 int32_t value) { 708 GPBFileSyntax syntax = [self descriptor].file.syntax; 709 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 710} 711 712void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, 713 GPBFieldDescriptor *field, int32_t value, 714 GPBFileSyntax syntax) { 715#if defined(DEBUG) && DEBUG 716 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum, 717 @"Attempting to set field %@ of %@ which is of type %@ with " 718 @"value of type Enum.", 719 [self class], field.name, 720 TypeToString(GPBGetFieldDataType(field))); 721#endif 722 // Don't allow in unknown values. Proto3 can use the Raw method. 723 if (![field isValidEnumValue:value]) { 724 [NSException raise:NSInvalidArgumentException 725 format:@"%@.%@: Attempt to set an unknown enum value (%d)", 726 [self class], field.name, value]; 727 } 728 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 729} 730 731// Only exists for public api, no core code should use this. 732int32_t GPBGetMessageRawEnumField(GPBMessage *self, 733 GPBFieldDescriptor *field) { 734 int32_t result = GPBGetMessageInt32Field(self, field); 735 return result; 736} 737 738// Only exists for public api, no core code should use this. 739void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, 740 int32_t value) { 741 GPBFileSyntax syntax = [self descriptor].file.syntax; 742 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 743} 744 745BOOL GPBGetMessageBoolField(GPBMessage *self, 746 GPBFieldDescriptor *field) { 747#if defined(DEBUG) && DEBUG 748 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), 749 @"Attempting to get value of type bool from field %@ " 750 @"of %@ which is of type %@.", 751 [self class], field.name, 752 TypeToString(GPBGetFieldDataType(field))); 753#endif 754 if (GPBGetHasIvarField(self, field)) { 755 // Bools are stored in the has bits to avoid needing explicit space in the 756 // storage structure. 757 // (the field number passed to the HasIvar helper doesn't really matter 758 // since the offset is never negative) 759 GPBMessageFieldDescription *fieldDesc = field->description_; 760 return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number); 761 } else { 762 return field.defaultValue.valueBool; 763 } 764} 765 766// Only exists for public api, no core code should use this. 767void GPBSetMessageBoolField(GPBMessage *self, 768 GPBFieldDescriptor *field, 769 BOOL value) { 770 if (self == nil || field == nil) return; 771 GPBFileSyntax syntax = [self descriptor].file.syntax; 772 GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); 773} 774 775void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, 776 GPBFieldDescriptor *field, 777 BOOL value, 778 GPBFileSyntax syntax) { 779#if defined(DEBUG) && DEBUG 780 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool), 781 @"Attempting to set field %@ of %@ which is of type %@ with " 782 @"value of type bool.", 783 [self class], field.name, 784 TypeToString(GPBGetFieldDataType(field))); 785#endif 786 GPBMessageFieldDescription *fieldDesc = field->description_; 787 GPBOneofDescriptor *oneof = field->containingOneof_; 788 if (oneof) { 789 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 790 } 791 792 // Bools are stored in the has bits to avoid needing explicit space in the 793 // storage structure. 794 // (the field number passed to the HasIvar helper doesn't really matter since 795 // the offset is never negative) 796 GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); 797 798 // proto2: any value counts as having been set; proto3, it 799 // has to be a non zero value or be in a oneof. 800 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 801 || (value != (BOOL)0) 802 || (field->containingOneof_ != NULL)); 803 GPBSetHasIvarField(self, field, hasValue); 804 GPBBecomeVisibleToAutocreator(self); 805} 806 807//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) 808// This block of code is generated, do not edit it directly. 809 810int32_t GPBGetMessageInt32Field(GPBMessage *self, 811 GPBFieldDescriptor *field) { 812#if defined(DEBUG) && DEBUG 813 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 814 GPBDataTypeInt32), 815 @"Attempting to get value of int32_t from field %@ " 816 @"of %@ which is of type %@.", 817 [self class], field.name, 818 TypeToString(GPBGetFieldDataType(field))); 819#endif 820 if (GPBGetHasIvarField(self, field)) { 821 uint8_t *storage = (uint8_t *)self->messageStorage_; 822 int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; 823 return *typePtr; 824 } else { 825 return field.defaultValue.valueInt32; 826 } 827} 828 829// Only exists for public api, no core code should use this. 830void GPBSetMessageInt32Field(GPBMessage *self, 831 GPBFieldDescriptor *field, 832 int32_t value) { 833 if (self == nil || field == nil) return; 834 GPBFileSyntax syntax = [self descriptor].file.syntax; 835 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 836} 837 838void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, 839 GPBFieldDescriptor *field, 840 int32_t value, 841 GPBFileSyntax syntax) { 842#if defined(DEBUG) && DEBUG 843 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 844 GPBDataTypeInt32), 845 @"Attempting to set field %@ of %@ which is of type %@ with " 846 @"value of type int32_t.", 847 [self class], field.name, 848 TypeToString(GPBGetFieldDataType(field))); 849#endif 850 GPBOneofDescriptor *oneof = field->containingOneof_; 851 if (oneof) { 852 GPBMessageFieldDescription *fieldDesc = field->description_; 853 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 854 } 855#if defined(DEBUG) && DEBUG 856 NSCAssert(self->messageStorage_ != NULL, 857 @"%@: All messages should have storage (from init)", 858 [self class]); 859#endif 860#if defined(__clang_analyzer__) 861 if (self->messageStorage_ == NULL) return; 862#endif 863 uint8_t *storage = (uint8_t *)self->messageStorage_; 864 int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; 865 *typePtr = value; 866 // proto2: any value counts as having been set; proto3, it 867 // has to be a non zero value or be in a oneof. 868 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 869 || (value != (int32_t)0) 870 || (field->containingOneof_ != NULL)); 871 GPBSetHasIvarField(self, field, hasValue); 872 GPBBecomeVisibleToAutocreator(self); 873} 874 875//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) 876// This block of code is generated, do not edit it directly. 877 878uint32_t GPBGetMessageUInt32Field(GPBMessage *self, 879 GPBFieldDescriptor *field) { 880#if defined(DEBUG) && DEBUG 881 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 882 GPBDataTypeUInt32), 883 @"Attempting to get value of uint32_t from field %@ " 884 @"of %@ which is of type %@.", 885 [self class], field.name, 886 TypeToString(GPBGetFieldDataType(field))); 887#endif 888 if (GPBGetHasIvarField(self, field)) { 889 uint8_t *storage = (uint8_t *)self->messageStorage_; 890 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; 891 return *typePtr; 892 } else { 893 return field.defaultValue.valueUInt32; 894 } 895} 896 897// Only exists for public api, no core code should use this. 898void GPBSetMessageUInt32Field(GPBMessage *self, 899 GPBFieldDescriptor *field, 900 uint32_t value) { 901 if (self == nil || field == nil) return; 902 GPBFileSyntax syntax = [self descriptor].file.syntax; 903 GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); 904} 905 906void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, 907 GPBFieldDescriptor *field, 908 uint32_t value, 909 GPBFileSyntax syntax) { 910#if defined(DEBUG) && DEBUG 911 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 912 GPBDataTypeUInt32), 913 @"Attempting to set field %@ of %@ which is of type %@ with " 914 @"value of type uint32_t.", 915 [self class], field.name, 916 TypeToString(GPBGetFieldDataType(field))); 917#endif 918 GPBOneofDescriptor *oneof = field->containingOneof_; 919 if (oneof) { 920 GPBMessageFieldDescription *fieldDesc = field->description_; 921 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 922 } 923#if defined(DEBUG) && DEBUG 924 NSCAssert(self->messageStorage_ != NULL, 925 @"%@: All messages should have storage (from init)", 926 [self class]); 927#endif 928#if defined(__clang_analyzer__) 929 if (self->messageStorage_ == NULL) return; 930#endif 931 uint8_t *storage = (uint8_t *)self->messageStorage_; 932 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; 933 *typePtr = value; 934 // proto2: any value counts as having been set; proto3, it 935 // has to be a non zero value or be in a oneof. 936 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 937 || (value != (uint32_t)0) 938 || (field->containingOneof_ != NULL)); 939 GPBSetHasIvarField(self, field, hasValue); 940 GPBBecomeVisibleToAutocreator(self); 941} 942 943//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) 944// This block of code is generated, do not edit it directly. 945 946int64_t GPBGetMessageInt64Field(GPBMessage *self, 947 GPBFieldDescriptor *field) { 948#if defined(DEBUG) && DEBUG 949 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 950 GPBDataTypeInt64), 951 @"Attempting to get value of int64_t from field %@ " 952 @"of %@ which is of type %@.", 953 [self class], field.name, 954 TypeToString(GPBGetFieldDataType(field))); 955#endif 956 if (GPBGetHasIvarField(self, field)) { 957 uint8_t *storage = (uint8_t *)self->messageStorage_; 958 int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; 959 return *typePtr; 960 } else { 961 return field.defaultValue.valueInt64; 962 } 963} 964 965// Only exists for public api, no core code should use this. 966void GPBSetMessageInt64Field(GPBMessage *self, 967 GPBFieldDescriptor *field, 968 int64_t value) { 969 if (self == nil || field == nil) return; 970 GPBFileSyntax syntax = [self descriptor].file.syntax; 971 GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); 972} 973 974void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, 975 GPBFieldDescriptor *field, 976 int64_t value, 977 GPBFileSyntax syntax) { 978#if defined(DEBUG) && DEBUG 979 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 980 GPBDataTypeInt64), 981 @"Attempting to set field %@ of %@ which is of type %@ with " 982 @"value of type int64_t.", 983 [self class], field.name, 984 TypeToString(GPBGetFieldDataType(field))); 985#endif 986 GPBOneofDescriptor *oneof = field->containingOneof_; 987 if (oneof) { 988 GPBMessageFieldDescription *fieldDesc = field->description_; 989 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 990 } 991#if defined(DEBUG) && DEBUG 992 NSCAssert(self->messageStorage_ != NULL, 993 @"%@: All messages should have storage (from init)", 994 [self class]); 995#endif 996#if defined(__clang_analyzer__) 997 if (self->messageStorage_ == NULL) return; 998#endif 999 uint8_t *storage = (uint8_t *)self->messageStorage_; 1000 int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; 1001 *typePtr = value; 1002 // proto2: any value counts as having been set; proto3, it 1003 // has to be a non zero value or be in a oneof. 1004 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 1005 || (value != (int64_t)0) 1006 || (field->containingOneof_ != NULL)); 1007 GPBSetHasIvarField(self, field, hasValue); 1008 GPBBecomeVisibleToAutocreator(self); 1009} 1010 1011//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) 1012// This block of code is generated, do not edit it directly. 1013 1014uint64_t GPBGetMessageUInt64Field(GPBMessage *self, 1015 GPBFieldDescriptor *field) { 1016#if defined(DEBUG) && DEBUG 1017 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1018 GPBDataTypeUInt64), 1019 @"Attempting to get value of uint64_t from field %@ " 1020 @"of %@ which is of type %@.", 1021 [self class], field.name, 1022 TypeToString(GPBGetFieldDataType(field))); 1023#endif 1024 if (GPBGetHasIvarField(self, field)) { 1025 uint8_t *storage = (uint8_t *)self->messageStorage_; 1026 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; 1027 return *typePtr; 1028 } else { 1029 return field.defaultValue.valueUInt64; 1030 } 1031} 1032 1033// Only exists for public api, no core code should use this. 1034void GPBSetMessageUInt64Field(GPBMessage *self, 1035 GPBFieldDescriptor *field, 1036 uint64_t value) { 1037 if (self == nil || field == nil) return; 1038 GPBFileSyntax syntax = [self descriptor].file.syntax; 1039 GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); 1040} 1041 1042void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, 1043 GPBFieldDescriptor *field, 1044 uint64_t value, 1045 GPBFileSyntax syntax) { 1046#if defined(DEBUG) && DEBUG 1047 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1048 GPBDataTypeUInt64), 1049 @"Attempting to set field %@ of %@ which is of type %@ with " 1050 @"value of type uint64_t.", 1051 [self class], field.name, 1052 TypeToString(GPBGetFieldDataType(field))); 1053#endif 1054 GPBOneofDescriptor *oneof = field->containingOneof_; 1055 if (oneof) { 1056 GPBMessageFieldDescription *fieldDesc = field->description_; 1057 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 1058 } 1059#if defined(DEBUG) && DEBUG 1060 NSCAssert(self->messageStorage_ != NULL, 1061 @"%@: All messages should have storage (from init)", 1062 [self class]); 1063#endif 1064#if defined(__clang_analyzer__) 1065 if (self->messageStorage_ == NULL) return; 1066#endif 1067 uint8_t *storage = (uint8_t *)self->messageStorage_; 1068 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; 1069 *typePtr = value; 1070 // proto2: any value counts as having been set; proto3, it 1071 // has to be a non zero value or be in a oneof. 1072 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 1073 || (value != (uint64_t)0) 1074 || (field->containingOneof_ != NULL)); 1075 GPBSetHasIvarField(self, field, hasValue); 1076 GPBBecomeVisibleToAutocreator(self); 1077} 1078 1079//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) 1080// This block of code is generated, do not edit it directly. 1081 1082float GPBGetMessageFloatField(GPBMessage *self, 1083 GPBFieldDescriptor *field) { 1084#if defined(DEBUG) && DEBUG 1085 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1086 GPBDataTypeFloat), 1087 @"Attempting to get value of float from field %@ " 1088 @"of %@ which is of type %@.", 1089 [self class], field.name, 1090 TypeToString(GPBGetFieldDataType(field))); 1091#endif 1092 if (GPBGetHasIvarField(self, field)) { 1093 uint8_t *storage = (uint8_t *)self->messageStorage_; 1094 float *typePtr = (float *)&storage[field->description_->offset]; 1095 return *typePtr; 1096 } else { 1097 return field.defaultValue.valueFloat; 1098 } 1099} 1100 1101// Only exists for public api, no core code should use this. 1102void GPBSetMessageFloatField(GPBMessage *self, 1103 GPBFieldDescriptor *field, 1104 float value) { 1105 if (self == nil || field == nil) return; 1106 GPBFileSyntax syntax = [self descriptor].file.syntax; 1107 GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); 1108} 1109 1110void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, 1111 GPBFieldDescriptor *field, 1112 float value, 1113 GPBFileSyntax syntax) { 1114#if defined(DEBUG) && DEBUG 1115 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1116 GPBDataTypeFloat), 1117 @"Attempting to set field %@ of %@ which is of type %@ with " 1118 @"value of type float.", 1119 [self class], field.name, 1120 TypeToString(GPBGetFieldDataType(field))); 1121#endif 1122 GPBOneofDescriptor *oneof = field->containingOneof_; 1123 if (oneof) { 1124 GPBMessageFieldDescription *fieldDesc = field->description_; 1125 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 1126 } 1127#if defined(DEBUG) && DEBUG 1128 NSCAssert(self->messageStorage_ != NULL, 1129 @"%@: All messages should have storage (from init)", 1130 [self class]); 1131#endif 1132#if defined(__clang_analyzer__) 1133 if (self->messageStorage_ == NULL) return; 1134#endif 1135 uint8_t *storage = (uint8_t *)self->messageStorage_; 1136 float *typePtr = (float *)&storage[field->description_->offset]; 1137 *typePtr = value; 1138 // proto2: any value counts as having been set; proto3, it 1139 // has to be a non zero value or be in a oneof. 1140 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 1141 || (value != (float)0) 1142 || (field->containingOneof_ != NULL)); 1143 GPBSetHasIvarField(self, field, hasValue); 1144 GPBBecomeVisibleToAutocreator(self); 1145} 1146 1147//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) 1148// This block of code is generated, do not edit it directly. 1149 1150double GPBGetMessageDoubleField(GPBMessage *self, 1151 GPBFieldDescriptor *field) { 1152#if defined(DEBUG) && DEBUG 1153 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1154 GPBDataTypeDouble), 1155 @"Attempting to get value of double from field %@ " 1156 @"of %@ which is of type %@.", 1157 [self class], field.name, 1158 TypeToString(GPBGetFieldDataType(field))); 1159#endif 1160 if (GPBGetHasIvarField(self, field)) { 1161 uint8_t *storage = (uint8_t *)self->messageStorage_; 1162 double *typePtr = (double *)&storage[field->description_->offset]; 1163 return *typePtr; 1164 } else { 1165 return field.defaultValue.valueDouble; 1166 } 1167} 1168 1169// Only exists for public api, no core code should use this. 1170void GPBSetMessageDoubleField(GPBMessage *self, 1171 GPBFieldDescriptor *field, 1172 double value) { 1173 if (self == nil || field == nil) return; 1174 GPBFileSyntax syntax = [self descriptor].file.syntax; 1175 GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); 1176} 1177 1178void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, 1179 GPBFieldDescriptor *field, 1180 double value, 1181 GPBFileSyntax syntax) { 1182#if defined(DEBUG) && DEBUG 1183 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1184 GPBDataTypeDouble), 1185 @"Attempting to set field %@ of %@ which is of type %@ with " 1186 @"value of type double.", 1187 [self class], field.name, 1188 TypeToString(GPBGetFieldDataType(field))); 1189#endif 1190 GPBOneofDescriptor *oneof = field->containingOneof_; 1191 if (oneof) { 1192 GPBMessageFieldDescription *fieldDesc = field->description_; 1193 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 1194 } 1195#if defined(DEBUG) && DEBUG 1196 NSCAssert(self->messageStorage_ != NULL, 1197 @"%@: All messages should have storage (from init)", 1198 [self class]); 1199#endif 1200#if defined(__clang_analyzer__) 1201 if (self->messageStorage_ == NULL) return; 1202#endif 1203 uint8_t *storage = (uint8_t *)self->messageStorage_; 1204 double *typePtr = (double *)&storage[field->description_->offset]; 1205 *typePtr = value; 1206 // proto2: any value counts as having been set; proto3, it 1207 // has to be a non zero value or be in a oneof. 1208 BOOL hasValue = ((syntax == GPBFileSyntaxProto2) 1209 || (value != (double)0) 1210 || (field->containingOneof_ != NULL)); 1211 GPBSetHasIvarField(self, field, hasValue); 1212 GPBBecomeVisibleToAutocreator(self); 1213} 1214 1215//%PDDM-EXPAND-END (6 expansions) 1216 1217// Aliases are function calls that are virtually the same. 1218 1219//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString) 1220// This block of code is generated, do not edit it directly. 1221 1222// Only exists for public api, no core code should use this. 1223NSString *GPBGetMessageStringField(GPBMessage *self, 1224 GPBFieldDescriptor *field) { 1225#if defined(DEBUG) && DEBUG 1226 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1227 GPBDataTypeString), 1228 @"Attempting to get value of NSString from field %@ " 1229 @"of %@ which is of type %@.", 1230 [self class], field.name, 1231 TypeToString(GPBGetFieldDataType(field))); 1232#endif 1233 return (NSString *)GPBGetObjectIvarWithField(self, field); 1234} 1235 1236// Only exists for public api, no core code should use this. 1237void GPBSetMessageStringField(GPBMessage *self, 1238 GPBFieldDescriptor *field, 1239 NSString *value) { 1240#if defined(DEBUG) && DEBUG 1241 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1242 GPBDataTypeString), 1243 @"Attempting to set field %@ of %@ which is of type %@ with " 1244 @"value of type NSString.", 1245 [self class], field.name, 1246 TypeToString(GPBGetFieldDataType(field))); 1247#endif 1248 GPBSetCopyObjectIvarWithField(self, field, (id)value); 1249} 1250 1251//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData) 1252// This block of code is generated, do not edit it directly. 1253 1254// Only exists for public api, no core code should use this. 1255NSData *GPBGetMessageBytesField(GPBMessage *self, 1256 GPBFieldDescriptor *field) { 1257#if defined(DEBUG) && DEBUG 1258 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1259 GPBDataTypeBytes), 1260 @"Attempting to get value of NSData from field %@ " 1261 @"of %@ which is of type %@.", 1262 [self class], field.name, 1263 TypeToString(GPBGetFieldDataType(field))); 1264#endif 1265 return (NSData *)GPBGetObjectIvarWithField(self, field); 1266} 1267 1268// Only exists for public api, no core code should use this. 1269void GPBSetMessageBytesField(GPBMessage *self, 1270 GPBFieldDescriptor *field, 1271 NSData *value) { 1272#if defined(DEBUG) && DEBUG 1273 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1274 GPBDataTypeBytes), 1275 @"Attempting to set field %@ of %@ which is of type %@ with " 1276 @"value of type NSData.", 1277 [self class], field.name, 1278 TypeToString(GPBGetFieldDataType(field))); 1279#endif 1280 GPBSetCopyObjectIvarWithField(self, field, (id)value); 1281} 1282 1283//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) 1284// This block of code is generated, do not edit it directly. 1285 1286// Only exists for public api, no core code should use this. 1287GPBMessage *GPBGetMessageMessageField(GPBMessage *self, 1288 GPBFieldDescriptor *field) { 1289#if defined(DEBUG) && DEBUG 1290 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1291 GPBDataTypeMessage), 1292 @"Attempting to get value of GPBMessage from field %@ " 1293 @"of %@ which is of type %@.", 1294 [self class], field.name, 1295 TypeToString(GPBGetFieldDataType(field))); 1296#endif 1297 return (GPBMessage *)GPBGetObjectIvarWithField(self, field); 1298} 1299 1300// Only exists for public api, no core code should use this. 1301void GPBSetMessageMessageField(GPBMessage *self, 1302 GPBFieldDescriptor *field, 1303 GPBMessage *value) { 1304#if defined(DEBUG) && DEBUG 1305 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1306 GPBDataTypeMessage), 1307 @"Attempting to set field %@ of %@ which is of type %@ with " 1308 @"value of type GPBMessage.", 1309 [self class], field.name, 1310 TypeToString(GPBGetFieldDataType(field))); 1311#endif 1312 GPBSetObjectIvarWithField(self, field, (id)value); 1313} 1314 1315//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) 1316// This block of code is generated, do not edit it directly. 1317 1318// Only exists for public api, no core code should use this. 1319GPBMessage *GPBGetMessageGroupField(GPBMessage *self, 1320 GPBFieldDescriptor *field) { 1321#if defined(DEBUG) && DEBUG 1322 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1323 GPBDataTypeGroup), 1324 @"Attempting to get value of GPBMessage from field %@ " 1325 @"of %@ which is of type %@.", 1326 [self class], field.name, 1327 TypeToString(GPBGetFieldDataType(field))); 1328#endif 1329 return (GPBMessage *)GPBGetObjectIvarWithField(self, field); 1330} 1331 1332// Only exists for public api, no core code should use this. 1333void GPBSetMessageGroupField(GPBMessage *self, 1334 GPBFieldDescriptor *field, 1335 GPBMessage *value) { 1336#if defined(DEBUG) && DEBUG 1337 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), 1338 GPBDataTypeGroup), 1339 @"Attempting to set field %@ of %@ which is of type %@ with " 1340 @"value of type GPBMessage.", 1341 [self class], field.name, 1342 TypeToString(GPBGetFieldDataType(field))); 1343#endif 1344 GPBSetObjectIvarWithField(self, field, (id)value); 1345} 1346 1347//%PDDM-EXPAND-END (4 expansions) 1348 1349// GPBGetMessageRepeatedField is defined in GPBMessage.m 1350 1351// Only exists for public api, no core code should use this. 1352void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { 1353#if defined(DEBUG) && DEBUG 1354 if (field.fieldType != GPBFieldTypeRepeated) { 1355 [NSException raise:NSInvalidArgumentException 1356 format:@"%@.%@ is not a repeated field.", 1357 [self class], field.name]; 1358 } 1359 Class expectedClass = Nil; 1360 switch (GPBGetFieldDataType(field)) { 1361 case GPBDataTypeBool: 1362 expectedClass = [GPBBoolArray class]; 1363 break; 1364 case GPBDataTypeSFixed32: 1365 case GPBDataTypeInt32: 1366 case GPBDataTypeSInt32: 1367 expectedClass = [GPBInt32Array class]; 1368 break; 1369 case GPBDataTypeFixed32: 1370 case GPBDataTypeUInt32: 1371 expectedClass = [GPBUInt32Array class]; 1372 break; 1373 case GPBDataTypeSFixed64: 1374 case GPBDataTypeInt64: 1375 case GPBDataTypeSInt64: 1376 expectedClass = [GPBInt64Array class]; 1377 break; 1378 case GPBDataTypeFixed64: 1379 case GPBDataTypeUInt64: 1380 expectedClass = [GPBUInt64Array class]; 1381 break; 1382 case GPBDataTypeFloat: 1383 expectedClass = [GPBFloatArray class]; 1384 break; 1385 case GPBDataTypeDouble: 1386 expectedClass = [GPBDoubleArray class]; 1387 break; 1388 case GPBDataTypeBytes: 1389 case GPBDataTypeString: 1390 case GPBDataTypeMessage: 1391 case GPBDataTypeGroup: 1392 expectedClass = [NSMutableArray class]; 1393 break; 1394 case GPBDataTypeEnum: 1395 expectedClass = [GPBEnumArray class]; 1396 break; 1397 } 1398 if (array && ![array isKindOfClass:expectedClass]) { 1399 [NSException raise:NSInvalidArgumentException 1400 format:@"%@.%@: Expected %@ object, got %@.", 1401 [self class], field.name, expectedClass, [array class]]; 1402 } 1403#endif 1404 GPBSetObjectIvarWithField(self, field, array); 1405} 1406 1407static GPBDataType BaseDataType(GPBDataType type) { 1408 switch (type) { 1409 case GPBDataTypeSFixed32: 1410 case GPBDataTypeInt32: 1411 case GPBDataTypeSInt32: 1412 case GPBDataTypeEnum: 1413 return GPBDataTypeInt32; 1414 case GPBDataTypeFixed32: 1415 case GPBDataTypeUInt32: 1416 return GPBDataTypeUInt32; 1417 case GPBDataTypeSFixed64: 1418 case GPBDataTypeInt64: 1419 case GPBDataTypeSInt64: 1420 return GPBDataTypeInt64; 1421 case GPBDataTypeFixed64: 1422 case GPBDataTypeUInt64: 1423 return GPBDataTypeUInt64; 1424 case GPBDataTypeMessage: 1425 case GPBDataTypeGroup: 1426 return GPBDataTypeMessage; 1427 case GPBDataTypeBool: 1428 case GPBDataTypeFloat: 1429 case GPBDataTypeDouble: 1430 case GPBDataTypeBytes: 1431 case GPBDataTypeString: 1432 return type; 1433 } 1434} 1435 1436static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) { 1437 return BaseDataType(type1) == BaseDataType(type2); 1438} 1439 1440static NSString *TypeToString(GPBDataType dataType) { 1441 switch (dataType) { 1442 case GPBDataTypeBool: 1443 return @"Bool"; 1444 case GPBDataTypeSFixed32: 1445 case GPBDataTypeInt32: 1446 case GPBDataTypeSInt32: 1447 return @"Int32"; 1448 case GPBDataTypeFixed32: 1449 case GPBDataTypeUInt32: 1450 return @"UInt32"; 1451 case GPBDataTypeSFixed64: 1452 case GPBDataTypeInt64: 1453 case GPBDataTypeSInt64: 1454 return @"Int64"; 1455 case GPBDataTypeFixed64: 1456 case GPBDataTypeUInt64: 1457 return @"UInt64"; 1458 case GPBDataTypeFloat: 1459 return @"Float"; 1460 case GPBDataTypeDouble: 1461 return @"Double"; 1462 case GPBDataTypeBytes: 1463 case GPBDataTypeString: 1464 case GPBDataTypeMessage: 1465 case GPBDataTypeGroup: 1466 return @"Object"; 1467 case GPBDataTypeEnum: 1468 return @"Enum"; 1469 } 1470} 1471 1472// GPBGetMessageMapField is defined in GPBMessage.m 1473 1474// Only exists for public api, no core code should use this. 1475void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, 1476 id dictionary) { 1477#if defined(DEBUG) && DEBUG 1478 if (field.fieldType != GPBFieldTypeMap) { 1479 [NSException raise:NSInvalidArgumentException 1480 format:@"%@.%@ is not a map<> field.", 1481 [self class], field.name]; 1482 } 1483 if (dictionary) { 1484 GPBDataType keyDataType = field.mapKeyDataType; 1485 GPBDataType valueDataType = GPBGetFieldDataType(field); 1486 NSString *keyStr = TypeToString(keyDataType); 1487 NSString *valueStr = TypeToString(valueDataType); 1488 if (keyDataType == GPBDataTypeString) { 1489 keyStr = @"String"; 1490 } 1491 Class expectedClass = Nil; 1492 if ((keyDataType == GPBDataTypeString) && 1493 GPBDataTypeIsObject(valueDataType)) { 1494 expectedClass = [NSMutableDictionary class]; 1495 } else { 1496 NSString *className = 1497 [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; 1498 expectedClass = NSClassFromString(className); 1499 NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); 1500 } 1501 if (![dictionary isKindOfClass:expectedClass]) { 1502 [NSException raise:NSInvalidArgumentException 1503 format:@"%@.%@: Expected %@ object, got %@.", 1504 [self class], field.name, expectedClass, 1505 [dictionary class]]; 1506 } 1507 } 1508#endif 1509 GPBSetObjectIvarWithField(self, field, dictionary); 1510} 1511 1512#pragma mark - Misc Dynamic Runtime Utils 1513 1514const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { 1515 Protocol *protocol = 1516 objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol)); 1517 NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol"); 1518 struct objc_method_description description = 1519 protocol_getMethodDescription(protocol, selector, NO, instanceSel); 1520 NSCAssert(description.name != Nil && description.types != nil, 1521 @"Missing method for selector %@", NSStringFromSelector(selector)); 1522 return description.types; 1523} 1524 1525#pragma mark - Text Format Support 1526 1527static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) { 1528 [destStr appendString:@"\""]; 1529 NSUInteger len = [toPrint length]; 1530 for (NSUInteger i = 0; i < len; ++i) { 1531 unichar aChar = [toPrint characterAtIndex:i]; 1532 switch (aChar) { 1533 case '\n': [destStr appendString:@"\\n"]; break; 1534 case '\r': [destStr appendString:@"\\r"]; break; 1535 case '\t': [destStr appendString:@"\\t"]; break; 1536 case '\"': [destStr appendString:@"\\\""]; break; 1537 case '\'': [destStr appendString:@"\\\'"]; break; 1538 case '\\': [destStr appendString:@"\\\\"]; break; 1539 default: 1540 // This differs slightly from the C++ code in that the C++ doesn't 1541 // generate UTF8; it looks at the string in UTF8, but escapes every 1542 // byte > 0x7E. 1543 if (aChar < 0x20) { 1544 [destStr appendFormat:@"\\%d%d%d", 1545 (aChar / 64), ((aChar % 64) / 8), (aChar % 8)]; 1546 } else { 1547 [destStr appendFormat:@"%C", aChar]; 1548 } 1549 break; 1550 } 1551 } 1552 [destStr appendString:@"\""]; 1553} 1554 1555static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { 1556 const char *src = (const char *)[buffer bytes]; 1557 size_t srcLen = [buffer length]; 1558 [destStr appendString:@"\""]; 1559 for (const char *srcEnd = src + srcLen; src < srcEnd; src++) { 1560 switch (*src) { 1561 case '\n': [destStr appendString:@"\\n"]; break; 1562 case '\r': [destStr appendString:@"\\r"]; break; 1563 case '\t': [destStr appendString:@"\\t"]; break; 1564 case '\"': [destStr appendString:@"\\\""]; break; 1565 case '\'': [destStr appendString:@"\\\'"]; break; 1566 case '\\': [destStr appendString:@"\\\\"]; break; 1567 default: 1568 if (isprint(*src)) { 1569 [destStr appendFormat:@"%c", *src]; 1570 } else { 1571 // NOTE: doing hex means you have to worry about the letter after 1572 // the hex being another hex char and forcing that to be escaped, so 1573 // use octal to keep it simple. 1574 [destStr appendFormat:@"\\%03o", (uint8_t)(*src)]; 1575 } 1576 break; 1577 } 1578 } 1579 [destStr appendString:@"\""]; 1580} 1581 1582static void AppendTextFormatForMapMessageField( 1583 id map, GPBFieldDescriptor *field, NSMutableString *toStr, 1584 NSString *lineIndent, NSString *fieldName, NSString *lineEnding) { 1585 GPBDataType keyDataType = field.mapKeyDataType; 1586 GPBDataType valueDataType = GPBGetFieldDataType(field); 1587 BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); 1588 1589 NSString *msgStartFirst = 1590 [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; 1591 NSString *msgStart = 1592 [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName]; 1593 NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent]; 1594 1595 NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent]; 1596 NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent, 1597 (isMessageValue ? "" : ":")]; 1598 1599 __block BOOL isFirst = YES; 1600 1601 if ((keyDataType == GPBDataTypeString) && 1602 GPBDataTypeIsObject(valueDataType)) { 1603 // map is an NSDictionary. 1604 NSDictionary *dict = map; 1605 [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { 1606 #pragma unused(stop) 1607 [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; 1608 isFirst = NO; 1609 1610 [toStr appendString:keyLine]; 1611 AppendStringEscaped(key, toStr); 1612 [toStr appendString:@"\n"]; 1613 1614 [toStr appendString:valueLine]; 1615#pragma clang diagnostic push 1616#pragma clang diagnostic ignored "-Wswitch-enum" 1617 switch (valueDataType) { 1618 case GPBDataTypeString: 1619 AppendStringEscaped(value, toStr); 1620 break; 1621 1622 case GPBDataTypeBytes: 1623 AppendBufferAsString(value, toStr); 1624 break; 1625 1626 case GPBDataTypeMessage: 1627 [toStr appendString:@"{\n"]; 1628 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1629 AppendTextFormatForMessage(value, toStr, subIndent); 1630 [toStr appendFormat:@"%@ }", lineIndent]; 1631 break; 1632 1633 default: 1634 NSCAssert(NO, @"Can't happen"); 1635 break; 1636 } 1637#pragma clang diagnostic pop 1638 [toStr appendString:@"\n"]; 1639 1640 [toStr appendString:msgEnd]; 1641 }]; 1642 } else { 1643 // map is one of the GPB*Dictionary classes, type doesn't matter. 1644 GPBInt32Int32Dictionary *dict = map; 1645 [dict enumerateForTextFormat:^(id keyObj, id valueObj) { 1646 [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; 1647 isFirst = NO; 1648 1649 // Key always is a NSString. 1650 if (keyDataType == GPBDataTypeString) { 1651 [toStr appendString:keyLine]; 1652 AppendStringEscaped(keyObj, toStr); 1653 [toStr appendString:@"\n"]; 1654 } else { 1655 [toStr appendFormat:@"%@%@\n", keyLine, keyObj]; 1656 } 1657 1658 [toStr appendString:valueLine]; 1659#pragma clang diagnostic push 1660#pragma clang diagnostic ignored "-Wswitch-enum" 1661 switch (valueDataType) { 1662 case GPBDataTypeString: 1663 AppendStringEscaped(valueObj, toStr); 1664 break; 1665 1666 case GPBDataTypeBytes: 1667 AppendBufferAsString(valueObj, toStr); 1668 break; 1669 1670 case GPBDataTypeMessage: 1671 [toStr appendString:@"{\n"]; 1672 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1673 AppendTextFormatForMessage(valueObj, toStr, subIndent); 1674 [toStr appendFormat:@"%@ }", lineIndent]; 1675 break; 1676 1677 case GPBDataTypeEnum: { 1678 int32_t enumValue = [valueObj intValue]; 1679 NSString *valueStr = nil; 1680 GPBEnumDescriptor *descriptor = field.enumDescriptor; 1681 if (descriptor) { 1682 valueStr = [descriptor textFormatNameForValue:enumValue]; 1683 } 1684 if (valueStr) { 1685 [toStr appendString:valueStr]; 1686 } else { 1687 [toStr appendFormat:@"%d", enumValue]; 1688 } 1689 break; 1690 } 1691 1692 default: 1693 NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); 1694 // Everything else is a NSString. 1695 [toStr appendString:valueObj]; 1696 break; 1697 } 1698#pragma clang diagnostic pop 1699 [toStr appendString:@"\n"]; 1700 1701 [toStr appendString:msgEnd]; 1702 }]; 1703 } 1704} 1705 1706static void AppendTextFormatForMessageField(GPBMessage *message, 1707 GPBFieldDescriptor *field, 1708 NSMutableString *toStr, 1709 NSString *lineIndent) { 1710 id arrayOrMap; 1711 NSUInteger count; 1712 GPBFieldType fieldType = field.fieldType; 1713 switch (fieldType) { 1714 case GPBFieldTypeSingle: 1715 arrayOrMap = nil; 1716 count = (GPBGetHasIvarField(message, field) ? 1 : 0); 1717 break; 1718 1719 case GPBFieldTypeRepeated: 1720 // Will be NSArray or GPB*Array, type doesn't matter, they both 1721 // implement count. 1722 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); 1723 count = [(NSArray *)arrayOrMap count]; 1724 break; 1725 1726 case GPBFieldTypeMap: { 1727 // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter, 1728 // they both implement count. 1729 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); 1730 count = [(NSDictionary *)arrayOrMap count]; 1731 break; 1732 } 1733 } 1734 1735 if (count == 0) { 1736 // Nothing to print, out of here. 1737 return; 1738 } 1739 1740 NSString *lineEnding = @""; 1741 1742 // If the name can't be reversed or support for extra info was turned off, 1743 // this can return nil. 1744 NSString *fieldName = [field textFormatName]; 1745 if ([fieldName length] == 0) { 1746 fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)]; 1747 // If there is only one entry, put the objc name as a comment, other wise 1748 // add it before the repeated values. 1749 if (count > 1) { 1750 [toStr appendFormat:@"%@# %@\n", lineIndent, field.name]; 1751 } else { 1752 lineEnding = [NSString stringWithFormat:@" # %@", field.name]; 1753 } 1754 } 1755 1756 if (fieldType == GPBFieldTypeMap) { 1757 AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, 1758 fieldName, lineEnding); 1759 return; 1760 } 1761 1762 id array = arrayOrMap; 1763 const BOOL isRepeated = (array != nil); 1764 1765 GPBDataType fieldDataType = GPBGetFieldDataType(field); 1766 BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); 1767 for (NSUInteger j = 0; j < count; ++j) { 1768 // Start the line. 1769 [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, 1770 (isMessageField ? "" : ":")]; 1771 1772 // The value. 1773 switch (fieldDataType) { 1774#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ 1775 case GPBDataType##GPBDATATYPE: { \ 1776 CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ 1777 : GPBGetMessage##REAL_TYPE##Field(message, field)); \ 1778 [toStr appendFormat:__VA_ARGS__, v]; \ 1779 break; \ 1780 } 1781 1782 FIELD_CASE(Int32, int32_t, Int32, @"%d") 1783 FIELD_CASE(SInt32, int32_t, Int32, @"%d") 1784 FIELD_CASE(SFixed32, int32_t, Int32, @"%d") 1785 FIELD_CASE(UInt32, uint32_t, UInt32, @"%u") 1786 FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u") 1787 FIELD_CASE(Int64, int64_t, Int64, @"%lld") 1788 FIELD_CASE(SInt64, int64_t, Int64, @"%lld") 1789 FIELD_CASE(SFixed64, int64_t, Int64, @"%lld") 1790 FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu") 1791 FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu") 1792 FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG) 1793 FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG) 1794 1795#undef FIELD_CASE 1796 1797 case GPBDataTypeEnum: { 1798 int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] 1799 : GPBGetMessageInt32Field(message, field)); 1800 NSString *valueStr = nil; 1801 GPBEnumDescriptor *descriptor = field.enumDescriptor; 1802 if (descriptor) { 1803 valueStr = [descriptor textFormatNameForValue:v]; 1804 } 1805 if (valueStr) { 1806 [toStr appendString:valueStr]; 1807 } else { 1808 [toStr appendFormat:@"%d", v]; 1809 } 1810 break; 1811 } 1812 1813 case GPBDataTypeBool: { 1814 BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] 1815 : GPBGetMessageBoolField(message, field)); 1816 [toStr appendString:(v ? @"true" : @"false")]; 1817 break; 1818 } 1819 1820 case GPBDataTypeString: { 1821 NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] 1822 : GPBGetMessageStringField(message, field)); 1823 AppendStringEscaped(v, toStr); 1824 break; 1825 } 1826 1827 case GPBDataTypeBytes: { 1828 NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] 1829 : GPBGetMessageBytesField(message, field)); 1830 AppendBufferAsString(v, toStr); 1831 break; 1832 } 1833 1834 case GPBDataTypeGroup: 1835 case GPBDataTypeMessage: { 1836 GPBMessage *v = 1837 (isRepeated ? [(NSArray *)array objectAtIndex:j] 1838 : GPBGetObjectIvarWithField(message, field)); 1839 [toStr appendFormat:@"{%@\n", lineEnding]; 1840 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1841 AppendTextFormatForMessage(v, toStr, subIndent); 1842 [toStr appendFormat:@"%@}", lineIndent]; 1843 lineEnding = @""; 1844 break; 1845 } 1846 1847 } // switch(fieldDataType) 1848 1849 // End the line. 1850 [toStr appendFormat:@"%@\n", lineEnding]; 1851 1852 } // for(count) 1853} 1854 1855static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, 1856 NSArray *activeExtensions, 1857 GPBExtensionRange range, 1858 NSMutableString *toStr, 1859 NSString *lineIndent) { 1860 uint32_t start = range.start; 1861 uint32_t end = range.end; 1862 for (GPBExtensionDescriptor *extension in activeExtensions) { 1863 uint32_t fieldNumber = extension.fieldNumber; 1864 if (fieldNumber < start) { 1865 // Not there yet. 1866 continue; 1867 } 1868 if (fieldNumber >= end) { 1869 // Done. 1870 break; 1871 } 1872 1873 id rawExtValue = [message getExtension:extension]; 1874 BOOL isRepeated = extension.isRepeated; 1875 1876 NSUInteger numValues = 1; 1877 NSString *lineEnding = @""; 1878 if (isRepeated) { 1879 numValues = [(NSArray *)rawExtValue count]; 1880 } 1881 1882 NSString *singletonName = extension.singletonName; 1883 if (numValues == 1) { 1884 lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; 1885 } else { 1886 [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; 1887 } 1888 1889 GPBDataType extDataType = extension.dataType; 1890 for (NSUInteger j = 0; j < numValues; ++j) { 1891 id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue); 1892 1893 // Start the line. 1894 [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber, 1895 (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; 1896 1897 // The value. 1898 switch (extDataType) { 1899#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ 1900 case GPBDataType##GPBDATATYPE: { \ 1901 CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ 1902 [toStr appendFormat:__VA_ARGS__, v]; \ 1903 break; \ 1904 } 1905 1906 FIELD_CASE(Int32, int32_t, intValue, @"%d") 1907 FIELD_CASE(SInt32, int32_t, intValue, @"%d") 1908 FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d") 1909 FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u") 1910 FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u") 1911 FIELD_CASE(Int64, int64_t, longLongValue, @"%lld") 1912 FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld") 1913 FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld") 1914 FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu") 1915 FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu") 1916 FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG) 1917 FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG) 1918 // TODO: Add a comment with the enum name from enum descriptors 1919 // (might not be real value, so leave it as a comment, ObjC compiler 1920 // name mangles differently). Doesn't look like we actually generate 1921 // an enum descriptor reference like we do for normal fields, so this 1922 // will take a compiler change. 1923 FIELD_CASE(Enum, int32_t, intValue, @"%d") 1924 1925#undef FIELD_CASE 1926 1927 case GPBDataTypeBool: 1928 [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" 1929 : @"false")]; 1930 break; 1931 1932 case GPBDataTypeString: 1933 AppendStringEscaped(curValue, toStr); 1934 break; 1935 1936 case GPBDataTypeBytes: 1937 AppendBufferAsString((NSData *)curValue, toStr); 1938 break; 1939 1940 case GPBDataTypeGroup: 1941 case GPBDataTypeMessage: { 1942 [toStr appendFormat:@"{%@\n", lineEnding]; 1943 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1944 AppendTextFormatForMessage(curValue, toStr, subIndent); 1945 [toStr appendFormat:@"%@}", lineIndent]; 1946 lineEnding = @""; 1947 break; 1948 } 1949 1950 } // switch(extDataType) 1951 1952 // End the line. 1953 [toStr appendFormat:@"%@\n", lineEnding]; 1954 1955 } // for(numValues) 1956 1957 } // for..in(activeExtensions) 1958} 1959 1960static void AppendTextFormatForMessage(GPBMessage *message, 1961 NSMutableString *toStr, 1962 NSString *lineIndent) { 1963 GPBDescriptor *descriptor = [message descriptor]; 1964 NSArray *fieldsArray = descriptor->fields_; 1965 NSUInteger fieldCount = fieldsArray.count; 1966 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; 1967 NSUInteger extensionRangesCount = descriptor.extensionRangesCount; 1968 NSArray *activeExtensions = [[message extensionsCurrentlySet] 1969 sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; 1970 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { 1971 if (i == fieldCount) { 1972 AppendTextFormatForMessageExtensionRange( 1973 message, activeExtensions, extensionRanges[j++], toStr, lineIndent); 1974 } else if (j == extensionRangesCount || 1975 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { 1976 AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, 1977 lineIndent); 1978 } else { 1979 AppendTextFormatForMessageExtensionRange( 1980 message, activeExtensions, extensionRanges[j++], toStr, lineIndent); 1981 } 1982 } 1983 1984 NSString *unknownFieldsStr = 1985 GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); 1986 if ([unknownFieldsStr length] > 0) { 1987 [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; 1988 [toStr appendString:unknownFieldsStr]; 1989 } 1990} 1991 1992NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { 1993 if (message == nil) return @""; 1994 if (lineIndent == nil) lineIndent = @""; 1995 1996 NSMutableString *buildString = [NSMutableString string]; 1997 AppendTextFormatForMessage(message, buildString, lineIndent); 1998 return buildString; 1999} 2000 2001NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, 2002 NSString *lineIndent) { 2003 if (unknownSet == nil) return @""; 2004 if (lineIndent == nil) lineIndent = @""; 2005 2006 NSMutableString *result = [NSMutableString string]; 2007 for (GPBUnknownField *field in [unknownSet sortedFields]) { 2008 int32_t fieldNumber = [field number]; 2009 2010#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ 2011 [field.PROPNAME \ 2012 enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \ 2013 _Pragma("unused(idx, stop)"); \ 2014 [result \ 2015 appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \ 2016 }]; 2017 2018 PRINT_LOOP(varintList, uint64_t, %llu); 2019 PRINT_LOOP(fixed32List, uint32_t, 0x%X); 2020 PRINT_LOOP(fixed64List, uint64_t, 0x%llX); 2021 2022#undef PRINT_LOOP 2023 2024 // NOTE: C++ version of TextFormat tries to parse this as a message 2025 // and print that if it succeeds. 2026 for (NSData *data in field.lengthDelimitedList) { 2027 [result appendFormat:@"%@%d: ", lineIndent, fieldNumber]; 2028 AppendBufferAsString(data, result); 2029 [result appendString:@"\n"]; 2030 } 2031 2032 for (GPBUnknownFieldSet *subUnknownSet in field.groupList) { 2033 [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; 2034 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 2035 NSString *subUnknwonSetStr = 2036 GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent); 2037 [result appendString:subUnknwonSetStr]; 2038 [result appendFormat:@"%@}\n", lineIndent]; 2039 } 2040 } 2041 return result; 2042} 2043 2044// Helpers to decode a varint. Not using GPBCodedInputStream version because 2045// that needs a state object, and we don't want to create an input stream out 2046// of the data. 2047GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) { 2048 int8_t result = *((int8_t *)(*data)); 2049 ++(*data); 2050 return result; 2051} 2052 2053static int32_t ReadRawVarint32FromData(const uint8_t **data) { 2054 int8_t tmp = ReadRawByteFromData(data); 2055 if (tmp >= 0) { 2056 return tmp; 2057 } 2058 int32_t result = tmp & 0x7f; 2059 if ((tmp = ReadRawByteFromData(data)) >= 0) { 2060 result |= tmp << 7; 2061 } else { 2062 result |= (tmp & 0x7f) << 7; 2063 if ((tmp = ReadRawByteFromData(data)) >= 0) { 2064 result |= tmp << 14; 2065 } else { 2066 result |= (tmp & 0x7f) << 14; 2067 if ((tmp = ReadRawByteFromData(data)) >= 0) { 2068 result |= tmp << 21; 2069 } else { 2070 result |= (tmp & 0x7f) << 21; 2071 result |= (tmp = ReadRawByteFromData(data)) << 28; 2072 if (tmp < 0) { 2073 // Discard upper 32 bits. 2074 for (int i = 0; i < 5; i++) { 2075 if (ReadRawByteFromData(data) >= 0) { 2076 return result; 2077 } 2078 } 2079 [NSException raise:NSParseErrorException 2080 format:@"Unable to read varint32"]; 2081 } 2082 } 2083 } 2084 } 2085 return result; 2086} 2087 2088NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, 2089 NSString *inputStr) { 2090 // decodData form: 2091 // varint32: num entries 2092 // for each entry: 2093 // varint32: key 2094 // bytes*: decode data 2095 // 2096 // decode data one of two forms: 2097 // 1: a \0 followed by the string followed by an \0 2098 // 2: bytecodes to transform an input into the right thing, ending with \0 2099 // 2100 // the bytes codes are of the form: 2101 // 0xabbccccc 2102 // 0x0 (all zeros), end. 2103 // a - if set, add an underscore 2104 // bb - 00 ccccc bytes as is 2105 // bb - 10 ccccc upper first, as is on rest, ccccc byte total 2106 // bb - 01 ccccc lower first, as is on rest, ccccc byte total 2107 // bb - 11 ccccc all upper, ccccc byte total 2108 2109 if (!decodeData || !inputStr) { 2110 return nil; 2111 } 2112 2113 // Find key 2114 const uint8_t *scan = decodeData; 2115 int32_t numEntries = ReadRawVarint32FromData(&scan); 2116 BOOL foundKey = NO; 2117 while (!foundKey && (numEntries > 0)) { 2118 --numEntries; 2119 int32_t dataKey = ReadRawVarint32FromData(&scan); 2120 if (dataKey == key) { 2121 foundKey = YES; 2122 } else { 2123 // If it is a inlined string, it will start with \0; if it is bytecode it 2124 // will start with a code. So advance one (skipping the inline string 2125 // marker), and then loop until reaching the end marker (\0). 2126 ++scan; 2127 while (*scan != 0) ++scan; 2128 // Now move past the end marker. 2129 ++scan; 2130 } 2131 } 2132 2133 if (!foundKey) { 2134 return nil; 2135 } 2136 2137 // Decode 2138 2139 if (*scan == 0) { 2140 // Inline string. Move over the marker, and NSString can take it as 2141 // UTF8. 2142 ++scan; 2143 NSString *result = [NSString stringWithUTF8String:(const char *)scan]; 2144 return result; 2145 } 2146 2147 NSMutableString *result = 2148 [NSMutableString stringWithCapacity:[inputStr length]]; 2149 2150 const uint8_t kAddUnderscore = 0b10000000; 2151 const uint8_t kOpMask = 0b01100000; 2152 // const uint8_t kOpAsIs = 0b00000000; 2153 const uint8_t kOpFirstUpper = 0b01000000; 2154 const uint8_t kOpFirstLower = 0b00100000; 2155 const uint8_t kOpAllUpper = 0b01100000; 2156 const uint8_t kSegmentLenMask = 0b00011111; 2157 2158 NSInteger i = 0; 2159 for (; *scan != 0; ++scan) { 2160 if (*scan & kAddUnderscore) { 2161 [result appendString:@"_"]; 2162 } 2163 int segmentLen = *scan & kSegmentLenMask; 2164 uint8_t decodeOp = *scan & kOpMask; 2165 2166 // Do op specific handling of the first character. 2167 if (decodeOp == kOpFirstUpper) { 2168 unichar c = [inputStr characterAtIndex:i]; 2169 [result appendFormat:@"%c", toupper((char)c)]; 2170 ++i; 2171 --segmentLen; 2172 } else if (decodeOp == kOpFirstLower) { 2173 unichar c = [inputStr characterAtIndex:i]; 2174 [result appendFormat:@"%c", tolower((char)c)]; 2175 ++i; 2176 --segmentLen; 2177 } 2178 // else op == kOpAsIs || op == kOpAllUpper 2179 2180 // Now pull over the rest of the length for this segment. 2181 for (int x = 0; x < segmentLen; ++x) { 2182 unichar c = [inputStr characterAtIndex:(i + x)]; 2183 if (decodeOp == kOpAllUpper) { 2184 [result appendFormat:@"%c", toupper((char)c)]; 2185 } else { 2186 [result appendFormat:@"%C", c]; 2187 } 2188 } 2189 i += segmentLen; 2190 } 2191 2192 return result; 2193} 2194 2195#pragma clang diagnostic pop 2196 2197BOOL GPBClassHasSel(Class aClass, SEL sel) { 2198 // NOTE: We have to use class_copyMethodList, all other runtime method 2199 // lookups actually also resolve the method implementation and this 2200 // is called from within those methods. 2201 2202 BOOL result = NO; 2203 unsigned int methodCount = 0; 2204 Method *methodList = class_copyMethodList(aClass, &methodCount); 2205 for (unsigned int i = 0; i < methodCount; ++i) { 2206 SEL methodSelector = method_getName(methodList[i]); 2207 if (methodSelector == sel) { 2208 result = YES; 2209 break; 2210 } 2211 } 2212 free(methodList); 2213 return result; 2214} 2215