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