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 52NSData *GPBEmptyNSData(void) { 53 static dispatch_once_t onceToken; 54 static NSData *defaultNSData = nil; 55 dispatch_once(&onceToken, ^{ 56 defaultNSData = [[NSData alloc] init]; 57 }); 58 return defaultNSData; 59} 60 61void GPBCheckRuntimeVersionInternal(int32_t version) { 62 if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) { 63 [NSException raise:NSInternalInconsistencyException 64 format:@"Linked to ProtocolBuffer runtime version %d," 65 @" but code compiled with version %d!", 66 GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; 67 } 68} 69 70BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { 71 GPBDescriptor *descriptor = [self descriptor]; 72 GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; 73 return GPBMessageHasFieldSet(self, field); 74} 75 76BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) { 77 if (self == nil || field == nil) return NO; 78 79 // Repeated/Map don't use the bit, they check the count. 80 if (GPBFieldIsMapOrArray(field)) { 81 // Array/map type doesn't matter, since GPB*Array/NSArray and 82 // GPB*Dictionary/NSDictionary all support -count; 83 NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 84 return (arrayOrMap.count > 0); 85 } else { 86 return GPBGetHasIvarField(self, field); 87 } 88} 89 90void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { 91 // If not set, nothing to do. 92 if (!GPBGetHasIvarField(self, field)) { 93 return; 94 } 95 96 if (GPBFieldStoresObject(field)) { 97 // Object types are handled slightly differently, they need to be released. 98 uint8_t *storage = (uint8_t *)self->messageStorage_; 99 id *typePtr = (id *)&storage[field->description_->offset]; 100 [*typePtr release]; 101 *typePtr = nil; 102 } else { 103 // POD types just need to clear the has bit as the Get* method will 104 // fetch the default when needed. 105 } 106 GPBSetHasIvarField(self, field, NO); 107} 108 109BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { 110 NSCAssert(self->messageStorage_ != NULL, 111 @"%@: All messages should have storage (from init)", 112 [self class]); 113 if (idx < 0) { 114 NSCAssert(fieldNumber != 0, @"Invalid field number."); 115 BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber); 116 return hasIvar; 117 } else { 118 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); 119 uint32_t byteIndex = idx / 32; 120 uint32_t bitMask = (1 << (idx % 32)); 121 BOOL hasIvar = 122 (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO; 123 return hasIvar; 124 } 125} 126 127uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) { 128 NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", 129 [self class], idx); 130 uint32_t result = self->messageStorage_->_has_storage_[-idx]; 131 return result; 132} 133 134void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, 135 BOOL value) { 136 if (idx < 0) { 137 NSCAssert(fieldNumber != 0, @"Invalid field number."); 138 uint32_t *has_storage = self->messageStorage_->_has_storage_; 139 has_storage[-idx] = (value ? fieldNumber : 0); 140 } else { 141 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit."); 142 uint32_t *has_storage = self->messageStorage_->_has_storage_; 143 uint32_t byte = idx / 32; 144 uint32_t bitMask = (1 << (idx % 32)); 145 if (value) { 146 has_storage[byte] |= bitMask; 147 } else { 148 has_storage[byte] &= ~bitMask; 149 } 150 } 151} 152 153void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, 154 int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { 155 uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); 156 if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { 157 // Do nothing/nothing set in the oneof. 158 return; 159 } 160 161 // Like GPBClearMessageField(), free the memory if an objecttype is set, 162 // pod types don't need to do anything. 163 GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet]; 164 NSCAssert(fieldSet, 165 @"%@: oneof set to something (%u) not in the oneof?", 166 [self class], fieldNumberSet); 167 if (fieldSet && GPBFieldStoresObject(fieldSet)) { 168 uint8_t *storage = (uint8_t *)self->messageStorage_; 169 id *typePtr = (id *)&storage[fieldSet->description_->offset]; 170 [*typePtr release]; 171 *typePtr = nil; 172 } 173 174 // Set to nothing stored in the oneof. 175 // (field number doesn't matter since setting to nothing). 176 GPBSetHasIvar(self, oneofHasIndex, 1, NO); 177} 178 179#pragma mark - IVar accessors 180 181//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) 182//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, 183//% TYPE$S NAME$S GPBFieldDescriptor *field) { 184//% if (GPBGetHasIvarField(self, field)) { 185//% uint8_t *storage = (uint8_t *)self->messageStorage_; 186//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; 187//% return *typePtr; 188//% } else { 189//% return field.defaultValue.value##NAME; 190//% } 191//%} 192//% 193//%// Only exists for public api, no core code should use this. 194//%void GPBSetMessage##NAME##Field(GPBMessage *self, 195//% NAME$S GPBFieldDescriptor *field, 196//% NAME$S TYPE value) { 197//% if (self == nil || field == nil) return; 198//% GPBFileSyntax syntax = [self descriptor].file.syntax; 199//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); 200//%} 201//% 202//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self, 203//% NAME$S GPBFieldDescriptor *field, 204//% NAME$S TYPE value, 205//% NAME$S GPBFileSyntax syntax) { 206//% GPBOneofDescriptor *oneof = field->containingOneof_; 207//% if (oneof) { 208//% GPBMessageFieldDescription *fieldDesc = field->description_; 209//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 210//% } 211//% NSCAssert(self->messageStorage_ != NULL, 212//% @"%@: All messages should have storage (from init)", 213//% [self class]); 214//%#if defined(__clang_analyzer__) 215//% if (self->messageStorage_ == NULL) return; 216//%#endif 217//% uint8_t *storage = (uint8_t *)self->messageStorage_; 218//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; 219//% *typePtr = value; 220//% // proto2: any value counts as having been set; proto3, it 221//% // has to be a non zero value. 222//% BOOL hasValue = 223//% (syntax == GPBFileSyntaxProto2) || (value != (TYPE)0); 224//% GPBSetHasIvarField(self, field, hasValue); 225//% GPBBecomeVisibleToAutocreator(self); 226//%} 227//% 228//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE) 229//%// Only exists for public api, no core code should use this. 230//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, 231//% TYPE$S NAME$S GPBFieldDescriptor *field) { 232//% return (TYPE *)GPBGetObjectIvarWithField(self, field); 233//%} 234//% 235//%// Only exists for public api, no core code should use this. 236//%void GPBSetMessage##NAME##Field(GPBMessage *self, 237//% NAME$S GPBFieldDescriptor *field, 238//% NAME$S TYPE *value) { 239//% GPBSetObjectIvarWithField(self, field, (id)value); 240//%} 241//% 242 243// Object types are handled slightly differently, they need to be released 244// and retained. 245 246void GPBSetAutocreatedRetainedObjectIvarWithField( 247 GPBMessage *self, GPBFieldDescriptor *field, 248 id __attribute__((ns_consumed)) value) { 249 uint8_t *storage = (uint8_t *)self->messageStorage_; 250 id *typePtr = (id *)&storage[field->description_->offset]; 251 NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); 252 *typePtr = value; 253} 254 255void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, 256 GPBFieldDescriptor *field) { 257 if (GPBGetHasIvarField(self, field)) { 258 return; 259 } 260 uint8_t *storage = (uint8_t *)self->messageStorage_; 261 id *typePtr = (id *)&storage[field->description_->offset]; 262 GPBMessage *oldValue = *typePtr; 263 *typePtr = NULL; 264 GPBClearMessageAutocreator(oldValue); 265 [oldValue release]; 266} 267 268// This exists only for briging some aliased types, nothing else should use it. 269static void GPBSetObjectIvarWithField(GPBMessage *self, 270 GPBFieldDescriptor *field, id value) { 271 if (self == nil || field == nil) return; 272 GPBFileSyntax syntax = [self descriptor].file.syntax; 273 GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], 274 syntax); 275} 276 277void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, 278 GPBFieldDescriptor *field, id value, 279 GPBFileSyntax syntax) { 280 GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], 281 syntax); 282} 283 284void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, 285 GPBFieldDescriptor *field, 286 id value, GPBFileSyntax syntax) { 287 NSCAssert(self->messageStorage_ != NULL, 288 @"%@: All messages should have storage (from init)", 289 [self class]); 290#if defined(__clang_analyzer__) 291 if (self->messageStorage_ == NULL) return; 292#endif 293 GPBDataType fieldType = GPBGetFieldDataType(field); 294 BOOL isMapOrArray = GPBFieldIsMapOrArray(field); 295 BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); 296#ifdef DEBUG 297 if (value == nil && !isMapOrArray && !fieldIsMessage && 298 field.hasDefaultValue) { 299 // Setting a message to nil is an obvious way to "clear" the value 300 // as there is no way to set a non-empty default value for messages. 301 // 302 // For Strings and Bytes that have default values set it is not clear what 303 // should be done when their value is set to nil. Is the intention just to 304 // clear the set value and reset to default, or is the intention to set the 305 // value to the empty string/data? Arguments can be made for both cases. 306 // 'nil' has been abused as a replacement for an empty string/data in ObjC. 307 // We decided to be consistent with all "object" types and clear the has 308 // field, and fall back on the default value. The warning below will only 309 // appear in debug, but the could should be changed so the intention is 310 // clear. 311 NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_); 312 NSString *propName = field.name; 313 NSString *className = self.descriptor.name; 314 NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " 315 @"default values. Please use '%@.%@ = %@' if you want to set it to " 316 @"empty, or call '%@.%@ = NO' to reset it to it's default value of " 317 @"'%@'. Defaulting to resetting default value.", 318 className, propName, className, propName, 319 (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", 320 className, hasSel, field.defaultValue.valueString); 321 // Note: valueString, depending on the type, it could easily be 322 // valueData/valueMessage. 323 } 324#endif // DEBUG 325 if (!isMapOrArray) { 326 // Non repeated/map can be in an oneof, clear any existing value from the 327 // oneof. 328 GPBOneofDescriptor *oneof = field->containingOneof_; 329 if (oneof) { 330 GPBMessageFieldDescription *fieldDesc = field->description_; 331 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 332 } 333 // Clear "has" if they are being set to nil. 334 BOOL setHasValue = (value != nil); 335 // Under proto3, Bytes & String fields get cleared by resetting them to 336 // their default (empty) values, so if they are set to something of length 337 // zero, they are being cleared. 338 if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && 339 ([value length] == 0)) { 340 setHasValue = NO; 341 value = nil; 342 } 343 GPBSetHasIvarField(self, field, setHasValue); 344 } 345 uint8_t *storage = (uint8_t *)self->messageStorage_; 346 id *typePtr = (id *)&storage[field->description_->offset]; 347 348 id oldValue = *typePtr; 349 350 *typePtr = value; 351 352 if (oldValue) { 353 if (isMapOrArray) { 354 if (field.fieldType == GPBFieldTypeRepeated) { 355 // If the old array was autocreated by us, then clear it. 356 if (GPBDataTypeIsObject(fieldType)) { 357 GPBAutocreatedArray *autoArray = oldValue; 358 if (autoArray->_autocreator == self) { 359 autoArray->_autocreator = nil; 360 } 361 } else { 362 // Type doesn't matter, it is a GPB*Array. 363 GPBInt32Array *gpbArray = oldValue; 364 if (gpbArray->_autocreator == self) { 365 gpbArray->_autocreator = nil; 366 } 367 } 368 } else { // GPBFieldTypeMap 369 // If the old map was autocreated by us, then clear it. 370 if ((field.mapKeyDataType == GPBDataTypeString) && 371 GPBDataTypeIsObject(fieldType)) { 372 GPBAutocreatedDictionary *autoDict = oldValue; 373 if (autoDict->_autocreator == self) { 374 autoDict->_autocreator = nil; 375 } 376 } else { 377 // Type doesn't matter, it is a GPB*Dictionary. 378 GPBInt32Int32Dictionary *gpbDict = oldValue; 379 if (gpbDict->_autocreator == self) { 380 gpbDict->_autocreator = nil; 381 } 382 } 383 } 384 } else if (fieldIsMessage) { 385 // If the old message value was autocreated by us, then clear it. 386 GPBMessage *oldMessageValue = oldValue; 387 if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) { 388 GPBClearMessageAutocreator(oldMessageValue); 389 } 390 } 391 [oldValue release]; 392 } 393 394 GPBBecomeVisibleToAutocreator(self); 395} 396 397id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, 398 GPBFieldDescriptor *field) { 399 if (self->messageStorage_ == nil) { 400 return nil; 401 } 402 uint8_t *storage = (uint8_t *)self->messageStorage_; 403 id *typePtr = (id *)&storage[field->description_->offset]; 404 return *typePtr; 405} 406 407id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 408 NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); 409 if (GPBGetHasIvarField(self, field)) { 410 uint8_t *storage = (uint8_t *)self->messageStorage_; 411 id *typePtr = (id *)&storage[field->description_->offset]; 412 return *typePtr; 413 } 414 // Not set... 415 416 // Non messages (string/data), get their default. 417 if (!GPBFieldDataTypeIsMessage(field)) { 418 return field.defaultValue.valueMessage; 419 } 420 421 GPBPrepareReadOnlySemaphore(self); 422 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); 423 GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 424 if (!result) { 425 // For non repeated messages, create the object, set it and return it. 426 // This object will not initially be visible via GPBGetHasIvar, so 427 // we save its creator so it can become visible if it's mutated later. 428 result = GPBCreateMessageWithAutocreator(field.msgClass, self, field); 429 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result); 430 } 431 dispatch_semaphore_signal(self->readOnlySemaphore_); 432 return result; 433} 434 435// Only exists for public api, no core code should use this. 436int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { 437 GPBFileSyntax syntax = [self descriptor].file.syntax; 438 return GPBGetEnumIvarWithFieldInternal(self, field, syntax); 439} 440 441int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, 442 GPBFieldDescriptor *field, 443 GPBFileSyntax syntax) { 444 int32_t result = GPBGetMessageInt32Field(self, field); 445 // If this is presevering unknown enums, make sure the value is valid before 446 // returning it. 447 if (GPBHasPreservingUnknownEnumSemantics(syntax) && 448 ![field isValidEnumValue:result]) { 449 result = kGPBUnrecognizedEnumeratorValue; 450 } 451 return result; 452} 453 454// Only exists for public api, no core code should use this. 455void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, 456 int32_t value) { 457 GPBFileSyntax syntax = [self descriptor].file.syntax; 458 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 459} 460 461void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, 462 GPBFieldDescriptor *field, int32_t value, 463 GPBFileSyntax syntax) { 464 // Don't allow in unknown values. Proto3 can use the Raw method. 465 if (![field isValidEnumValue:value]) { 466 [NSException raise:NSInvalidArgumentException 467 format:@"%@.%@: Attempt to set an unknown enum value (%d)", 468 [self class], field.name, value]; 469 } 470 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 471} 472 473// Only exists for public api, no core code should use this. 474int32_t GPBGetMessageRawEnumField(GPBMessage *self, 475 GPBFieldDescriptor *field) { 476 int32_t result = GPBGetMessageInt32Field(self, field); 477 return result; 478} 479 480// Only exists for public api, no core code should use this. 481void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, 482 int32_t value) { 483 GPBFileSyntax syntax = [self descriptor].file.syntax; 484 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 485} 486 487BOOL GPBGetMessageBoolField(GPBMessage *self, 488 GPBFieldDescriptor *field) { 489 if (GPBGetHasIvarField(self, field)) { 490 // Bools are stored in the has bits to avoid needing explicit space in the 491 // storage structure. 492 // (the field number passed to the HasIvar helper doesn't really matter 493 // since the offset is never negative) 494 GPBMessageFieldDescription *fieldDesc = field->description_; 495 return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number); 496 } else { 497 return field.defaultValue.valueBool; 498 } 499} 500 501// Only exists for public api, no core code should use this. 502void GPBSetMessageBoolField(GPBMessage *self, 503 GPBFieldDescriptor *field, 504 BOOL value) { 505 if (self == nil || field == nil) return; 506 GPBFileSyntax syntax = [self descriptor].file.syntax; 507 GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); 508} 509 510void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, 511 GPBFieldDescriptor *field, 512 BOOL value, 513 GPBFileSyntax syntax) { 514 GPBMessageFieldDescription *fieldDesc = field->description_; 515 GPBOneofDescriptor *oneof = field->containingOneof_; 516 if (oneof) { 517 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 518 } 519 520 // Bools are stored in the has bits to avoid needing explicit space in the 521 // storage structure. 522 // (the field number passed to the HasIvar helper doesn't really matter since 523 // the offset is never negative) 524 GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value); 525 526 // proto2: any value counts as having been set; proto3, it 527 // has to be a non zero value. 528 BOOL hasValue = 529 (syntax == GPBFileSyntaxProto2) || (value != (BOOL)0); 530 GPBSetHasIvarField(self, field, hasValue); 531 GPBBecomeVisibleToAutocreator(self); 532} 533 534//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) 535// This block of code is generated, do not edit it directly. 536 537int32_t GPBGetMessageInt32Field(GPBMessage *self, 538 GPBFieldDescriptor *field) { 539 if (GPBGetHasIvarField(self, field)) { 540 uint8_t *storage = (uint8_t *)self->messageStorage_; 541 int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; 542 return *typePtr; 543 } else { 544 return field.defaultValue.valueInt32; 545 } 546} 547 548// Only exists for public api, no core code should use this. 549void GPBSetMessageInt32Field(GPBMessage *self, 550 GPBFieldDescriptor *field, 551 int32_t value) { 552 if (self == nil || field == nil) return; 553 GPBFileSyntax syntax = [self descriptor].file.syntax; 554 GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); 555} 556 557void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, 558 GPBFieldDescriptor *field, 559 int32_t value, 560 GPBFileSyntax syntax) { 561 GPBOneofDescriptor *oneof = field->containingOneof_; 562 if (oneof) { 563 GPBMessageFieldDescription *fieldDesc = field->description_; 564 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 565 } 566 NSCAssert(self->messageStorage_ != NULL, 567 @"%@: All messages should have storage (from init)", 568 [self class]); 569#if defined(__clang_analyzer__) 570 if (self->messageStorage_ == NULL) return; 571#endif 572 uint8_t *storage = (uint8_t *)self->messageStorage_; 573 int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; 574 *typePtr = value; 575 // proto2: any value counts as having been set; proto3, it 576 // has to be a non zero value. 577 BOOL hasValue = 578 (syntax == GPBFileSyntaxProto2) || (value != (int32_t)0); 579 GPBSetHasIvarField(self, field, hasValue); 580 GPBBecomeVisibleToAutocreator(self); 581} 582 583//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) 584// This block of code is generated, do not edit it directly. 585 586uint32_t GPBGetMessageUInt32Field(GPBMessage *self, 587 GPBFieldDescriptor *field) { 588 if (GPBGetHasIvarField(self, field)) { 589 uint8_t *storage = (uint8_t *)self->messageStorage_; 590 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; 591 return *typePtr; 592 } else { 593 return field.defaultValue.valueUInt32; 594 } 595} 596 597// Only exists for public api, no core code should use this. 598void GPBSetMessageUInt32Field(GPBMessage *self, 599 GPBFieldDescriptor *field, 600 uint32_t value) { 601 if (self == nil || field == nil) return; 602 GPBFileSyntax syntax = [self descriptor].file.syntax; 603 GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); 604} 605 606void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, 607 GPBFieldDescriptor *field, 608 uint32_t value, 609 GPBFileSyntax syntax) { 610 GPBOneofDescriptor *oneof = field->containingOneof_; 611 if (oneof) { 612 GPBMessageFieldDescription *fieldDesc = field->description_; 613 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 614 } 615 NSCAssert(self->messageStorage_ != NULL, 616 @"%@: All messages should have storage (from init)", 617 [self class]); 618#if defined(__clang_analyzer__) 619 if (self->messageStorage_ == NULL) return; 620#endif 621 uint8_t *storage = (uint8_t *)self->messageStorage_; 622 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; 623 *typePtr = value; 624 // proto2: any value counts as having been set; proto3, it 625 // has to be a non zero value. 626 BOOL hasValue = 627 (syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0); 628 GPBSetHasIvarField(self, field, hasValue); 629 GPBBecomeVisibleToAutocreator(self); 630} 631 632//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) 633// This block of code is generated, do not edit it directly. 634 635int64_t GPBGetMessageInt64Field(GPBMessage *self, 636 GPBFieldDescriptor *field) { 637 if (GPBGetHasIvarField(self, field)) { 638 uint8_t *storage = (uint8_t *)self->messageStorage_; 639 int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; 640 return *typePtr; 641 } else { 642 return field.defaultValue.valueInt64; 643 } 644} 645 646// Only exists for public api, no core code should use this. 647void GPBSetMessageInt64Field(GPBMessage *self, 648 GPBFieldDescriptor *field, 649 int64_t value) { 650 if (self == nil || field == nil) return; 651 GPBFileSyntax syntax = [self descriptor].file.syntax; 652 GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); 653} 654 655void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, 656 GPBFieldDescriptor *field, 657 int64_t value, 658 GPBFileSyntax syntax) { 659 GPBOneofDescriptor *oneof = field->containingOneof_; 660 if (oneof) { 661 GPBMessageFieldDescription *fieldDesc = field->description_; 662 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 663 } 664 NSCAssert(self->messageStorage_ != NULL, 665 @"%@: All messages should have storage (from init)", 666 [self class]); 667#if defined(__clang_analyzer__) 668 if (self->messageStorage_ == NULL) return; 669#endif 670 uint8_t *storage = (uint8_t *)self->messageStorage_; 671 int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; 672 *typePtr = value; 673 // proto2: any value counts as having been set; proto3, it 674 // has to be a non zero value. 675 BOOL hasValue = 676 (syntax == GPBFileSyntaxProto2) || (value != (int64_t)0); 677 GPBSetHasIvarField(self, field, hasValue); 678 GPBBecomeVisibleToAutocreator(self); 679} 680 681//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) 682// This block of code is generated, do not edit it directly. 683 684uint64_t GPBGetMessageUInt64Field(GPBMessage *self, 685 GPBFieldDescriptor *field) { 686 if (GPBGetHasIvarField(self, field)) { 687 uint8_t *storage = (uint8_t *)self->messageStorage_; 688 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; 689 return *typePtr; 690 } else { 691 return field.defaultValue.valueUInt64; 692 } 693} 694 695// Only exists for public api, no core code should use this. 696void GPBSetMessageUInt64Field(GPBMessage *self, 697 GPBFieldDescriptor *field, 698 uint64_t value) { 699 if (self == nil || field == nil) return; 700 GPBFileSyntax syntax = [self descriptor].file.syntax; 701 GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); 702} 703 704void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, 705 GPBFieldDescriptor *field, 706 uint64_t value, 707 GPBFileSyntax syntax) { 708 GPBOneofDescriptor *oneof = field->containingOneof_; 709 if (oneof) { 710 GPBMessageFieldDescription *fieldDesc = field->description_; 711 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 712 } 713 NSCAssert(self->messageStorage_ != NULL, 714 @"%@: All messages should have storage (from init)", 715 [self class]); 716#if defined(__clang_analyzer__) 717 if (self->messageStorage_ == NULL) return; 718#endif 719 uint8_t *storage = (uint8_t *)self->messageStorage_; 720 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; 721 *typePtr = value; 722 // proto2: any value counts as having been set; proto3, it 723 // has to be a non zero value. 724 BOOL hasValue = 725 (syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0); 726 GPBSetHasIvarField(self, field, hasValue); 727 GPBBecomeVisibleToAutocreator(self); 728} 729 730//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) 731// This block of code is generated, do not edit it directly. 732 733float GPBGetMessageFloatField(GPBMessage *self, 734 GPBFieldDescriptor *field) { 735 if (GPBGetHasIvarField(self, field)) { 736 uint8_t *storage = (uint8_t *)self->messageStorage_; 737 float *typePtr = (float *)&storage[field->description_->offset]; 738 return *typePtr; 739 } else { 740 return field.defaultValue.valueFloat; 741 } 742} 743 744// Only exists for public api, no core code should use this. 745void GPBSetMessageFloatField(GPBMessage *self, 746 GPBFieldDescriptor *field, 747 float value) { 748 if (self == nil || field == nil) return; 749 GPBFileSyntax syntax = [self descriptor].file.syntax; 750 GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); 751} 752 753void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, 754 GPBFieldDescriptor *field, 755 float value, 756 GPBFileSyntax syntax) { 757 GPBOneofDescriptor *oneof = field->containingOneof_; 758 if (oneof) { 759 GPBMessageFieldDescription *fieldDesc = field->description_; 760 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 761 } 762 NSCAssert(self->messageStorage_ != NULL, 763 @"%@: All messages should have storage (from init)", 764 [self class]); 765#if defined(__clang_analyzer__) 766 if (self->messageStorage_ == NULL) return; 767#endif 768 uint8_t *storage = (uint8_t *)self->messageStorage_; 769 float *typePtr = (float *)&storage[field->description_->offset]; 770 *typePtr = value; 771 // proto2: any value counts as having been set; proto3, it 772 // has to be a non zero value. 773 BOOL hasValue = 774 (syntax == GPBFileSyntaxProto2) || (value != (float)0); 775 GPBSetHasIvarField(self, field, hasValue); 776 GPBBecomeVisibleToAutocreator(self); 777} 778 779//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) 780// This block of code is generated, do not edit it directly. 781 782double GPBGetMessageDoubleField(GPBMessage *self, 783 GPBFieldDescriptor *field) { 784 if (GPBGetHasIvarField(self, field)) { 785 uint8_t *storage = (uint8_t *)self->messageStorage_; 786 double *typePtr = (double *)&storage[field->description_->offset]; 787 return *typePtr; 788 } else { 789 return field.defaultValue.valueDouble; 790 } 791} 792 793// Only exists for public api, no core code should use this. 794void GPBSetMessageDoubleField(GPBMessage *self, 795 GPBFieldDescriptor *field, 796 double value) { 797 if (self == nil || field == nil) return; 798 GPBFileSyntax syntax = [self descriptor].file.syntax; 799 GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); 800} 801 802void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, 803 GPBFieldDescriptor *field, 804 double value, 805 GPBFileSyntax syntax) { 806 GPBOneofDescriptor *oneof = field->containingOneof_; 807 if (oneof) { 808 GPBMessageFieldDescription *fieldDesc = field->description_; 809 GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); 810 } 811 NSCAssert(self->messageStorage_ != NULL, 812 @"%@: All messages should have storage (from init)", 813 [self class]); 814#if defined(__clang_analyzer__) 815 if (self->messageStorage_ == NULL) return; 816#endif 817 uint8_t *storage = (uint8_t *)self->messageStorage_; 818 double *typePtr = (double *)&storage[field->description_->offset]; 819 *typePtr = value; 820 // proto2: any value counts as having been set; proto3, it 821 // has to be a non zero value. 822 BOOL hasValue = 823 (syntax == GPBFileSyntaxProto2) || (value != (double)0); 824 GPBSetHasIvarField(self, field, hasValue); 825 GPBBecomeVisibleToAutocreator(self); 826} 827 828//%PDDM-EXPAND-END (6 expansions) 829 830// Aliases are function calls that are virtually the same. 831 832//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString) 833// This block of code is generated, do not edit it directly. 834 835// Only exists for public api, no core code should use this. 836NSString *GPBGetMessageStringField(GPBMessage *self, 837 GPBFieldDescriptor *field) { 838 return (NSString *)GPBGetObjectIvarWithField(self, field); 839} 840 841// Only exists for public api, no core code should use this. 842void GPBSetMessageStringField(GPBMessage *self, 843 GPBFieldDescriptor *field, 844 NSString *value) { 845 GPBSetObjectIvarWithField(self, field, (id)value); 846} 847 848//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData) 849// This block of code is generated, do not edit it directly. 850 851// Only exists for public api, no core code should use this. 852NSData *GPBGetMessageBytesField(GPBMessage *self, 853 GPBFieldDescriptor *field) { 854 return (NSData *)GPBGetObjectIvarWithField(self, field); 855} 856 857// Only exists for public api, no core code should use this. 858void GPBSetMessageBytesField(GPBMessage *self, 859 GPBFieldDescriptor *field, 860 NSData *value) { 861 GPBSetObjectIvarWithField(self, field, (id)value); 862} 863 864//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) 865// This block of code is generated, do not edit it directly. 866 867// Only exists for public api, no core code should use this. 868GPBMessage *GPBGetMessageMessageField(GPBMessage *self, 869 GPBFieldDescriptor *field) { 870 return (GPBMessage *)GPBGetObjectIvarWithField(self, field); 871} 872 873// Only exists for public api, no core code should use this. 874void GPBSetMessageMessageField(GPBMessage *self, 875 GPBFieldDescriptor *field, 876 GPBMessage *value) { 877 GPBSetObjectIvarWithField(self, field, (id)value); 878} 879 880//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) 881// This block of code is generated, do not edit it directly. 882 883// Only exists for public api, no core code should use this. 884GPBMessage *GPBGetMessageGroupField(GPBMessage *self, 885 GPBFieldDescriptor *field) { 886 return (GPBMessage *)GPBGetObjectIvarWithField(self, field); 887} 888 889// Only exists for public api, no core code should use this. 890void GPBSetMessageGroupField(GPBMessage *self, 891 GPBFieldDescriptor *field, 892 GPBMessage *value) { 893 GPBSetObjectIvarWithField(self, field, (id)value); 894} 895 896//%PDDM-EXPAND-END (4 expansions) 897 898// GPBGetMessageRepeatedField is defined in GPBMessage.m 899 900// Only exists for public api, no core code should use this. 901void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { 902#if defined(DEBUG) && DEBUG 903 if (field.fieldType != GPBFieldTypeRepeated) { 904 [NSException raise:NSInvalidArgumentException 905 format:@"%@.%@ is not a repeated field.", 906 [self class], field.name]; 907 } 908 Class expectedClass = Nil; 909 switch (GPBGetFieldDataType(field)) { 910 case GPBDataTypeBool: 911 expectedClass = [GPBBoolArray class]; 912 break; 913 case GPBDataTypeSFixed32: 914 case GPBDataTypeInt32: 915 case GPBDataTypeSInt32: 916 expectedClass = [GPBInt32Array class]; 917 break; 918 case GPBDataTypeFixed32: 919 case GPBDataTypeUInt32: 920 expectedClass = [GPBUInt32Array class]; 921 break; 922 case GPBDataTypeSFixed64: 923 case GPBDataTypeInt64: 924 case GPBDataTypeSInt64: 925 expectedClass = [GPBInt64Array class]; 926 break; 927 case GPBDataTypeFixed64: 928 case GPBDataTypeUInt64: 929 expectedClass = [GPBUInt64Array class]; 930 break; 931 case GPBDataTypeFloat: 932 expectedClass = [GPBFloatArray class]; 933 break; 934 case GPBDataTypeDouble: 935 expectedClass = [GPBDoubleArray class]; 936 break; 937 case GPBDataTypeBytes: 938 case GPBDataTypeString: 939 case GPBDataTypeMessage: 940 case GPBDataTypeGroup: 941 expectedClass = [NSMutableArray class]; 942 break; 943 case GPBDataTypeEnum: 944 expectedClass = [GPBEnumArray class]; 945 break; 946 } 947 if (array && ![array isKindOfClass:expectedClass]) { 948 [NSException raise:NSInvalidArgumentException 949 format:@"%@.%@: Expected %@ object, got %@.", 950 [self class], field.name, expectedClass, [array class]]; 951 } 952#endif 953 GPBSetObjectIvarWithField(self, field, array); 954} 955 956#if defined(DEBUG) && DEBUG 957static NSString *TypeToStr(GPBDataType dataType) { 958 switch (dataType) { 959 case GPBDataTypeBool: 960 return @"Bool"; 961 case GPBDataTypeSFixed32: 962 case GPBDataTypeInt32: 963 case GPBDataTypeSInt32: 964 return @"Int32"; 965 case GPBDataTypeFixed32: 966 case GPBDataTypeUInt32: 967 return @"UInt32"; 968 case GPBDataTypeSFixed64: 969 case GPBDataTypeInt64: 970 case GPBDataTypeSInt64: 971 return @"Int64"; 972 case GPBDataTypeFixed64: 973 case GPBDataTypeUInt64: 974 return @"UInt64"; 975 case GPBDataTypeFloat: 976 return @"Float"; 977 case GPBDataTypeDouble: 978 return @"Double"; 979 case GPBDataTypeBytes: 980 case GPBDataTypeString: 981 case GPBDataTypeMessage: 982 case GPBDataTypeGroup: 983 return @"Object"; 984 case GPBDataTypeEnum: 985 return @"Bool"; 986 } 987} 988#endif 989 990// GPBGetMessageMapField is defined in GPBMessage.m 991 992// Only exists for public api, no core code should use this. 993void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, 994 id dictionary) { 995#if defined(DEBUG) && DEBUG 996 if (field.fieldType != GPBFieldTypeMap) { 997 [NSException raise:NSInvalidArgumentException 998 format:@"%@.%@ is not a map<> field.", 999 [self class], field.name]; 1000 } 1001 if (dictionary) { 1002 GPBDataType keyDataType = field.mapKeyDataType; 1003 GPBDataType valueDataType = GPBGetFieldDataType(field); 1004 NSString *keyStr = TypeToStr(keyDataType); 1005 NSString *valueStr = TypeToStr(valueDataType); 1006 if (keyDataType == GPBDataTypeString) { 1007 keyStr = @"String"; 1008 } 1009 Class expectedClass = Nil; 1010 if ((keyDataType == GPBDataTypeString) && 1011 GPBDataTypeIsObject(valueDataType)) { 1012 expectedClass = [NSMutableDictionary class]; 1013 } else { 1014 NSString *className = 1015 [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; 1016 expectedClass = NSClassFromString(className); 1017 NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); 1018 } 1019 if (![dictionary isKindOfClass:expectedClass]) { 1020 [NSException raise:NSInvalidArgumentException 1021 format:@"%@.%@: Expected %@ object, got %@.", 1022 [self class], field.name, expectedClass, 1023 [dictionary class]]; 1024 } 1025 } 1026#endif 1027 GPBSetObjectIvarWithField(self, field, dictionary); 1028} 1029 1030#pragma mark - Misc Dynamic Runtime Utils 1031 1032const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { 1033 Protocol *protocol = 1034 objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol)); 1035 struct objc_method_description description = 1036 protocol_getMethodDescription(protocol, selector, NO, instanceSel); 1037 return description.types; 1038} 1039 1040#pragma mark - Text Format Support 1041 1042static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) { 1043 [destStr appendString:@"\""]; 1044 NSUInteger len = [toPrint length]; 1045 for (NSUInteger i = 0; i < len; ++i) { 1046 unichar aChar = [toPrint characterAtIndex:i]; 1047 switch (aChar) { 1048 case '\n': [destStr appendString:@"\\n"]; break; 1049 case '\r': [destStr appendString:@"\\r"]; break; 1050 case '\t': [destStr appendString:@"\\t"]; break; 1051 case '\"': [destStr appendString:@"\\\""]; break; 1052 case '\'': [destStr appendString:@"\\\'"]; break; 1053 case '\\': [destStr appendString:@"\\\\"]; break; 1054 default: 1055 [destStr appendFormat:@"%C", aChar]; 1056 break; 1057 } 1058 } 1059 [destStr appendString:@"\""]; 1060} 1061 1062static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { 1063 const char *src = (const char *)[buffer bytes]; 1064 size_t srcLen = [buffer length]; 1065 [destStr appendString:@"\""]; 1066 for (const char *srcEnd = src + srcLen; src < srcEnd; src++) { 1067 switch (*src) { 1068 case '\n': [destStr appendString:@"\\n"]; break; 1069 case '\r': [destStr appendString:@"\\r"]; break; 1070 case '\t': [destStr appendString:@"\\t"]; break; 1071 case '\"': [destStr appendString:@"\\\""]; break; 1072 case '\'': [destStr appendString:@"\\\'"]; break; 1073 case '\\': [destStr appendString:@"\\\\"]; break; 1074 default: 1075 if (isprint(*src)) { 1076 [destStr appendFormat:@"%c", *src]; 1077 } else { 1078 // NOTE: doing hex means you have to worry about the letter after 1079 // the hex being another hex char and forcing that to be escaped, so 1080 // use octal to keep it simple. 1081 [destStr appendFormat:@"\\%03o", (uint8_t)(*src)]; 1082 } 1083 break; 1084 } 1085 } 1086 [destStr appendString:@"\""]; 1087} 1088 1089static void AppendTextFormatForMapMessageField( 1090 id map, GPBFieldDescriptor *field, NSMutableString *toStr, 1091 NSString *lineIndent, NSString *fieldName, NSString *lineEnding) { 1092 GPBDataType keyDataType = field.mapKeyDataType; 1093 GPBDataType valueDataType = GPBGetFieldDataType(field); 1094 BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); 1095 1096 NSString *msgStartFirst = 1097 [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; 1098 NSString *msgStart = 1099 [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName]; 1100 NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent]; 1101 1102 NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent]; 1103 NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent, 1104 (isMessageValue ? "" : ":")]; 1105 1106 __block BOOL isFirst = YES; 1107 1108 if ((keyDataType == GPBDataTypeString) && 1109 GPBDataTypeIsObject(valueDataType)) { 1110 // map is an NSDictionary. 1111 NSDictionary *dict = map; 1112 [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { 1113 #pragma unused(stop) 1114 [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; 1115 isFirst = NO; 1116 1117 [toStr appendString:keyLine]; 1118 AppendStringEscaped(key, toStr); 1119 [toStr appendString:@"\n"]; 1120 1121 [toStr appendString:valueLine]; 1122#pragma clang diagnostic push 1123#pragma clang diagnostic ignored "-Wswitch-enum" 1124 switch (valueDataType) { 1125 case GPBDataTypeString: 1126 AppendStringEscaped(value, toStr); 1127 break; 1128 1129 case GPBDataTypeBytes: 1130 AppendBufferAsString(value, toStr); 1131 break; 1132 1133 case GPBDataTypeMessage: 1134 [toStr appendString:@"{\n"]; 1135 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1136 AppendTextFormatForMessage(value, toStr, subIndent); 1137 [toStr appendFormat:@"%@ }", lineIndent]; 1138 break; 1139 1140 default: 1141 NSCAssert(NO, @"Can't happen"); 1142 break; 1143 } 1144#pragma clang diagnostic pop 1145 [toStr appendString:@"\n"]; 1146 1147 [toStr appendString:msgEnd]; 1148 }]; 1149 } else { 1150 // map is one of the GPB*Dictionary classes, type doesn't matter. 1151 GPBInt32Int32Dictionary *dict = map; 1152 [dict enumerateForTextFormat:^(id keyObj, id valueObj) { 1153 [toStr appendString:(isFirst ? msgStartFirst : msgStart)]; 1154 isFirst = NO; 1155 1156 // Key always is a NSString. 1157 if (keyDataType == GPBDataTypeString) { 1158 [toStr appendString:keyLine]; 1159 AppendStringEscaped(keyObj, toStr); 1160 [toStr appendString:@"\n"]; 1161 } else { 1162 [toStr appendFormat:@"%@%@\n", keyLine, keyObj]; 1163 } 1164 1165 [toStr appendString:valueLine]; 1166#pragma clang diagnostic push 1167#pragma clang diagnostic ignored "-Wswitch-enum" 1168 switch (valueDataType) { 1169 case GPBDataTypeString: 1170 AppendStringEscaped(valueObj, toStr); 1171 break; 1172 1173 case GPBDataTypeBytes: 1174 AppendBufferAsString(valueObj, toStr); 1175 break; 1176 1177 case GPBDataTypeMessage: 1178 [toStr appendString:@"{\n"]; 1179 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1180 AppendTextFormatForMessage(valueObj, toStr, subIndent); 1181 [toStr appendFormat:@"%@ }", lineIndent]; 1182 break; 1183 1184 case GPBDataTypeEnum: { 1185 int32_t enumValue = [valueObj intValue]; 1186 NSString *valueStr = nil; 1187 GPBEnumDescriptor *descriptor = field.enumDescriptor; 1188 if (descriptor) { 1189 valueStr = [descriptor textFormatNameForValue:enumValue]; 1190 } 1191 if (valueStr) { 1192 [toStr appendString:valueStr]; 1193 } else { 1194 [toStr appendFormat:@"%d", enumValue]; 1195 } 1196 break; 1197 } 1198 1199 default: 1200 NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); 1201 // Everything else is a NSString. 1202 [toStr appendString:valueObj]; 1203 break; 1204 } 1205#pragma clang diagnostic pop 1206 [toStr appendString:@"\n"]; 1207 1208 [toStr appendString:msgEnd]; 1209 }]; 1210 } 1211} 1212 1213static void AppendTextFormatForMessageField(GPBMessage *message, 1214 GPBFieldDescriptor *field, 1215 NSMutableString *toStr, 1216 NSString *lineIndent) { 1217 id arrayOrMap; 1218 NSUInteger count; 1219 GPBFieldType fieldType = field.fieldType; 1220 switch (fieldType) { 1221 case GPBFieldTypeSingle: 1222 arrayOrMap = nil; 1223 count = (GPBGetHasIvarField(message, field) ? 1 : 0); 1224 break; 1225 1226 case GPBFieldTypeRepeated: 1227 // Will be NSArray or GPB*Array, type doesn't matter, they both 1228 // implement count. 1229 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); 1230 count = [(NSArray *)arrayOrMap count]; 1231 break; 1232 1233 case GPBFieldTypeMap: { 1234 // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter, 1235 // they both implement count. 1236 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); 1237 count = [(NSDictionary *)arrayOrMap count]; 1238 break; 1239 } 1240 } 1241 1242 if (count == 0) { 1243 // Nothing to print, out of here. 1244 return; 1245 } 1246 1247 NSString *lineEnding = @""; 1248 1249 // If the name can't be reversed or support for extra info was turned off, 1250 // this can return nil. 1251 NSString *fieldName = [field textFormatName]; 1252 if ([fieldName length] == 0) { 1253 fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)]; 1254 // If there is only one entry, put the objc name as a comment, other wise 1255 // add it before the repeated values. 1256 if (count > 1) { 1257 [toStr appendFormat:@"%@# %@\n", lineIndent, field.name]; 1258 } else { 1259 lineEnding = [NSString stringWithFormat:@" # %@", field.name]; 1260 } 1261 } 1262 1263 if (fieldType == GPBFieldTypeMap) { 1264 AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, 1265 fieldName, lineEnding); 1266 return; 1267 } 1268 1269 id array = arrayOrMap; 1270 const BOOL isRepeated = (array != nil); 1271 1272 GPBDataType fieldDataType = GPBGetFieldDataType(field); 1273 BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); 1274 for (NSUInteger j = 0; j < count; ++j) { 1275 // Start the line. 1276 [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, 1277 (isMessageField ? "" : ":")]; 1278 1279 // The value. 1280 switch (fieldDataType) { 1281#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ 1282 case GPBDataType##GPBDATATYPE: { \ 1283 CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ 1284 : GPBGetMessage##REAL_TYPE##Field(message, field)); \ 1285 [toStr appendFormat:__VA_ARGS__, v]; \ 1286 break; \ 1287 } 1288 1289 FIELD_CASE(Int32, int32_t, Int32, @"%d") 1290 FIELD_CASE(SInt32, int32_t, Int32, @"%d") 1291 FIELD_CASE(SFixed32, int32_t, Int32, @"%d") 1292 FIELD_CASE(UInt32, uint32_t, UInt32, @"%u") 1293 FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u") 1294 FIELD_CASE(Int64, int64_t, Int64, @"%lld") 1295 FIELD_CASE(SInt64, int64_t, Int64, @"%lld") 1296 FIELD_CASE(SFixed64, int64_t, Int64, @"%lld") 1297 FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu") 1298 FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu") 1299 FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG) 1300 FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG) 1301 1302#undef FIELD_CASE 1303 1304 case GPBDataTypeEnum: { 1305 int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] 1306 : GPBGetMessageInt32Field(message, field)); 1307 NSString *valueStr = nil; 1308 GPBEnumDescriptor *descriptor = field.enumDescriptor; 1309 if (descriptor) { 1310 valueStr = [descriptor textFormatNameForValue:v]; 1311 } 1312 if (valueStr) { 1313 [toStr appendString:valueStr]; 1314 } else { 1315 [toStr appendFormat:@"%d", v]; 1316 } 1317 break; 1318 } 1319 1320 case GPBDataTypeBool: { 1321 BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] 1322 : GPBGetMessageBoolField(message, field)); 1323 [toStr appendString:(v ? @"true" : @"false")]; 1324 break; 1325 } 1326 1327 case GPBDataTypeString: { 1328 NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] 1329 : GPBGetMessageStringField(message, field)); 1330 AppendStringEscaped(v, toStr); 1331 break; 1332 } 1333 1334 case GPBDataTypeBytes: { 1335 NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] 1336 : GPBGetMessageBytesField(message, field)); 1337 AppendBufferAsString(v, toStr); 1338 break; 1339 } 1340 1341 case GPBDataTypeGroup: 1342 case GPBDataTypeMessage: { 1343 GPBMessage *v = 1344 (isRepeated ? [(NSArray *)array objectAtIndex:j] 1345 : GPBGetObjectIvarWithField(message, field)); 1346 [toStr appendFormat:@"{%@\n", lineEnding]; 1347 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1348 AppendTextFormatForMessage(v, toStr, subIndent); 1349 [toStr appendFormat:@"%@}", lineIndent]; 1350 lineEnding = @""; 1351 break; 1352 } 1353 1354 } // switch(fieldDataType) 1355 1356 // End the line. 1357 [toStr appendFormat:@"%@\n", lineEnding]; 1358 1359 } // for(count) 1360} 1361 1362static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, 1363 NSArray *activeExtensions, 1364 GPBExtensionRange range, 1365 NSMutableString *toStr, 1366 NSString *lineIndent) { 1367 uint32_t start = range.start; 1368 uint32_t end = range.end; 1369 for (GPBExtensionDescriptor *extension in activeExtensions) { 1370 uint32_t fieldNumber = extension.fieldNumber; 1371 if (fieldNumber < start) { 1372 // Not there yet. 1373 continue; 1374 } 1375 if (fieldNumber > end) { 1376 // Done. 1377 break; 1378 } 1379 1380 id rawExtValue = [message getExtension:extension]; 1381 BOOL isRepeated = extension.isRepeated; 1382 1383 NSUInteger numValues = 1; 1384 NSString *lineEnding = @""; 1385 if (isRepeated) { 1386 numValues = [(NSArray *)rawExtValue count]; 1387 } 1388 1389 NSString *singletonName = extension.singletonName; 1390 if (numValues == 1) { 1391 lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; 1392 } else { 1393 [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; 1394 } 1395 1396 GPBDataType extDataType = extension.dataType; 1397 for (NSUInteger j = 0; j < numValues; ++j) { 1398 id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue); 1399 1400 // Start the line. 1401 [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber, 1402 (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; 1403 1404 // The value. 1405 switch (extDataType) { 1406#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ 1407 case GPBDataType##GPBDATATYPE: { \ 1408 CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ 1409 [toStr appendFormat:__VA_ARGS__, v]; \ 1410 break; \ 1411 } 1412 1413 FIELD_CASE(Int32, int32_t, intValue, @"%d") 1414 FIELD_CASE(SInt32, int32_t, intValue, @"%d") 1415 FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d") 1416 FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u") 1417 FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u") 1418 FIELD_CASE(Int64, int64_t, longLongValue, @"%lld") 1419 FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld") 1420 FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld") 1421 FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu") 1422 FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu") 1423 FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG) 1424 FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG) 1425 // TODO: Add a comment with the enum name from enum descriptors 1426 // (might not be real value, so leave it as a comment, ObjC compiler 1427 // name mangles differently). Doesn't look like we actually generate 1428 // an enum descriptor reference like we do for normal fields, so this 1429 // will take a compiler change. 1430 FIELD_CASE(Enum, int32_t, intValue, @"%d") 1431 1432#undef FIELD_CASE 1433 1434 case GPBDataTypeBool: 1435 [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" 1436 : @"false")]; 1437 break; 1438 1439 case GPBDataTypeString: 1440 AppendStringEscaped(curValue, toStr); 1441 break; 1442 1443 case GPBDataTypeBytes: 1444 AppendBufferAsString((NSData *)curValue, toStr); 1445 break; 1446 1447 case GPBDataTypeGroup: 1448 case GPBDataTypeMessage: { 1449 [toStr appendFormat:@"{%@\n", lineEnding]; 1450 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1451 AppendTextFormatForMessage(curValue, toStr, subIndent); 1452 [toStr appendFormat:@"%@}", lineIndent]; 1453 lineEnding = @""; 1454 break; 1455 } 1456 1457 } // switch(extDataType) 1458 1459 } // for(numValues) 1460 1461 // End the line. 1462 [toStr appendFormat:@"%@\n", lineEnding]; 1463 1464 } // for..in(activeExtensions) 1465} 1466 1467static void AppendTextFormatForMessage(GPBMessage *message, 1468 NSMutableString *toStr, 1469 NSString *lineIndent) { 1470 GPBDescriptor *descriptor = [message descriptor]; 1471 NSArray *fieldsArray = descriptor->fields_; 1472 NSUInteger fieldCount = fieldsArray.count; 1473 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; 1474 NSUInteger extensionRangesCount = descriptor.extensionRangesCount; 1475 NSArray *activeExtensions = [[message extensionsCurrentlySet] 1476 sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; 1477 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { 1478 if (i == fieldCount) { 1479 AppendTextFormatForMessageExtensionRange( 1480 message, activeExtensions, extensionRanges[j++], toStr, lineIndent); 1481 } else if (j == extensionRangesCount || 1482 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { 1483 AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, 1484 lineIndent); 1485 } else { 1486 AppendTextFormatForMessageExtensionRange( 1487 message, activeExtensions, extensionRanges[j++], toStr, lineIndent); 1488 } 1489 } 1490 1491 NSString *unknownFieldsStr = 1492 GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); 1493 if ([unknownFieldsStr length] > 0) { 1494 [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; 1495 [toStr appendString:unknownFieldsStr]; 1496 } 1497} 1498 1499NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { 1500 if (message == nil) return @""; 1501 if (lineIndent == nil) lineIndent = @""; 1502 1503 NSMutableString *buildString = [NSMutableString string]; 1504 AppendTextFormatForMessage(message, buildString, lineIndent); 1505 return buildString; 1506} 1507 1508NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, 1509 NSString *lineIndent) { 1510 if (unknownSet == nil) return @""; 1511 if (lineIndent == nil) lineIndent = @""; 1512 1513 NSMutableString *result = [NSMutableString string]; 1514 for (GPBUnknownField *field in [unknownSet sortedFields]) { 1515 int32_t fieldNumber = [field number]; 1516 1517#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ 1518 [field.PROPNAME \ 1519 enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \ 1520 _Pragma("unused(idx, stop)"); \ 1521 [result \ 1522 appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \ 1523 }]; 1524 1525 PRINT_LOOP(varintList, uint64_t, %llu); 1526 PRINT_LOOP(fixed32List, uint32_t, 0x%X); 1527 PRINT_LOOP(fixed64List, uint64_t, 0x%llX); 1528 1529#undef PRINT_LOOP 1530 1531 // NOTE: C++ version of TextFormat tries to parse this as a message 1532 // and print that if it succeeds. 1533 for (NSData *data in field.lengthDelimitedList) { 1534 [result appendFormat:@"%@%d: ", lineIndent, fieldNumber]; 1535 AppendBufferAsString(data, result); 1536 [result appendString:@"\n"]; 1537 } 1538 1539 for (GPBUnknownFieldSet *subUnknownSet in field.groupList) { 1540 [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; 1541 NSString *subIndent = [lineIndent stringByAppendingString:@" "]; 1542 NSString *subUnknwonSetStr = 1543 GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent); 1544 [result appendString:subUnknwonSetStr]; 1545 [result appendFormat:@"%@}\n", lineIndent]; 1546 } 1547 } 1548 return result; 1549} 1550 1551// Helpers to decode a varint. Not using GPBCodedInputStream version because 1552// that needs a state object, and we don't want to create an input stream out 1553// of the data. 1554GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) { 1555 int8_t result = *((int8_t *)(*data)); 1556 ++(*data); 1557 return result; 1558} 1559 1560static int32_t ReadRawVarint32FromData(const uint8_t **data) { 1561 int8_t tmp = ReadRawByteFromData(data); 1562 if (tmp >= 0) { 1563 return tmp; 1564 } 1565 int32_t result = tmp & 0x7f; 1566 if ((tmp = ReadRawByteFromData(data)) >= 0) { 1567 result |= tmp << 7; 1568 } else { 1569 result |= (tmp & 0x7f) << 7; 1570 if ((tmp = ReadRawByteFromData(data)) >= 0) { 1571 result |= tmp << 14; 1572 } else { 1573 result |= (tmp & 0x7f) << 14; 1574 if ((tmp = ReadRawByteFromData(data)) >= 0) { 1575 result |= tmp << 21; 1576 } else { 1577 result |= (tmp & 0x7f) << 21; 1578 result |= (tmp = ReadRawByteFromData(data)) << 28; 1579 if (tmp < 0) { 1580 // Discard upper 32 bits. 1581 for (int i = 0; i < 5; i++) { 1582 if (ReadRawByteFromData(data) >= 0) { 1583 return result; 1584 } 1585 } 1586 [NSException raise:NSParseErrorException 1587 format:@"Unable to read varint32"]; 1588 } 1589 } 1590 } 1591 } 1592 return result; 1593} 1594 1595NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, 1596 NSString *inputStr) { 1597 // decodData form: 1598 // varint32: num entries 1599 // for each entry: 1600 // varint32: key 1601 // bytes*: decode data 1602 // 1603 // decode data one of two forms: 1604 // 1: a \0 followed by the string followed by an \0 1605 // 2: bytecodes to transform an input into the right thing, ending with \0 1606 // 1607 // the bytes codes are of the form: 1608 // 0xabbccccc 1609 // 0x0 (all zeros), end. 1610 // a - if set, add an underscore 1611 // bb - 00 ccccc bytes as is 1612 // bb - 10 ccccc upper first, as is on rest, ccccc byte total 1613 // bb - 01 ccccc lower first, as is on rest, ccccc byte total 1614 // bb - 11 ccccc all upper, ccccc byte total 1615 1616 if (!decodeData || !inputStr) { 1617 return nil; 1618 } 1619 1620 // Find key 1621 const uint8_t *scan = decodeData; 1622 int32_t numEntries = ReadRawVarint32FromData(&scan); 1623 BOOL foundKey = NO; 1624 while (!foundKey && (numEntries > 0)) { 1625 --numEntries; 1626 int32_t dataKey = ReadRawVarint32FromData(&scan); 1627 if (dataKey == key) { 1628 foundKey = YES; 1629 } else { 1630 // If it is a inlined string, it will start with \0; if it is bytecode it 1631 // will start with a code. So advance one (skipping the inline string 1632 // marker), and then loop until reaching the end marker (\0). 1633 ++scan; 1634 while (*scan != 0) ++scan; 1635 // Now move past the end marker. 1636 ++scan; 1637 } 1638 } 1639 1640 if (!foundKey) { 1641 return nil; 1642 } 1643 1644 // Decode 1645 1646 if (*scan == 0) { 1647 // Inline string. Move over the marker, and NSString can take it as 1648 // UTF8. 1649 ++scan; 1650 NSString *result = [NSString stringWithUTF8String:(const char *)scan]; 1651 return result; 1652 } 1653 1654 NSMutableString *result = 1655 [NSMutableString stringWithCapacity:[inputStr length]]; 1656 1657 const uint8_t kAddUnderscore = 0b10000000; 1658 const uint8_t kOpMask = 0b01100000; 1659 // const uint8_t kOpAsIs = 0b00000000; 1660 const uint8_t kOpFirstUpper = 0b01000000; 1661 const uint8_t kOpFirstLower = 0b00100000; 1662 const uint8_t kOpAllUpper = 0b01100000; 1663 const uint8_t kSegmentLenMask = 0b00011111; 1664 1665 NSInteger i = 0; 1666 for (; *scan != 0; ++scan) { 1667 if (*scan & kAddUnderscore) { 1668 [result appendString:@"_"]; 1669 } 1670 int segmentLen = *scan & kSegmentLenMask; 1671 uint8_t decodeOp = *scan & kOpMask; 1672 1673 // Do op specific handling of the first character. 1674 if (decodeOp == kOpFirstUpper) { 1675 unichar c = [inputStr characterAtIndex:i]; 1676 [result appendFormat:@"%c", toupper((char)c)]; 1677 ++i; 1678 --segmentLen; 1679 } else if (decodeOp == kOpFirstLower) { 1680 unichar c = [inputStr characterAtIndex:i]; 1681 [result appendFormat:@"%c", tolower((char)c)]; 1682 ++i; 1683 --segmentLen; 1684 } 1685 // else op == kOpAsIs || op == kOpAllUpper 1686 1687 // Now pull over the rest of the length for this segment. 1688 for (int x = 0; x < segmentLen; ++x) { 1689 unichar c = [inputStr characterAtIndex:(i + x)]; 1690 if (decodeOp == kOpAllUpper) { 1691 [result appendFormat:@"%c", toupper((char)c)]; 1692 } else { 1693 [result appendFormat:@"%C", c]; 1694 } 1695 } 1696 i += segmentLen; 1697 } 1698 1699 return result; 1700} 1701 1702#pragma clang diagnostic pop 1703 1704#pragma mark - GPBMessageSignatureProtocol 1705 1706// A series of selectors that are used solely to get @encoding values 1707// for them by the dynamic protobuf runtime code. An object using the protocol 1708// needs to be declared for the protocol to be valid at runtime. 1709@interface GPBMessageSignatureProtocol : NSObject<GPBMessageSignatureProtocol> 1710@end 1711@implementation GPBMessageSignatureProtocol 1712@end 1713