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