1 // Protocol Buffers - Google's data interchange format
 
   2 // Copyright 2008 Google Inc.  All rights reserved.
 
   3 // https://developers.google.com/protocol-buffers/
 
   5 // Redistribution and use in source and binary forms, with or without
 
   6 // modification, are permitted provided that the following conditions are
 
   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
 
  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.
 
  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.
 
  31 #import "GPBUtilities_PackagePrivate.h"
 
  33 #import <objc/runtime.h>
 
  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"
 
  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"
 
  48 static void AppendTextFormatForMessage(GPBMessage *message,
 
  49                                        NSMutableString *toStr,
 
  50                                        NSString *lineIndent);
 
  52 // Are two datatypes the same basic type representation (ex Int32 and SInt32).
 
  53 // Marked unused because currently only called from asserts/debug.
 
  54 static BOOL DataTypesEquivalent(GPBDataType type1,
 
  55                                 GPBDataType type2) __attribute__ ((unused));
 
  57 // Basic type representation for a type (ex: for SInt32 it is Int32).
 
  58 // Marked unused because currently only called from asserts/debug.
 
  59 static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused));
 
  61 // String name for a data type.
 
  62 // Marked unused because currently only called from asserts/debug.
 
  63 static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused));
 
  65 NSData *GPBEmptyNSData(void) {
 
  66   static dispatch_once_t onceToken;
 
  67   static NSData *defaultNSData = nil;
 
  68   dispatch_once(&onceToken, ^{
 
  69     defaultNSData = [[NSData alloc] init];
 
  74 void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) {
 
  75   if (!initialMessage) {
 
  79   // Use an array as a list to process to avoid recursion.
 
  80   NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage];
 
  83     GPBMessage *msg = todo.lastObject;
 
  84     [todo removeLastObject];
 
  87     msg.unknownFields = nil;
 
  89     // Handle the message fields.
 
  90     GPBDescriptor *descriptor = [[msg class] descriptor];
 
  91     for (GPBFieldDescriptor *field in descriptor->fields_) {
 
  92       if (!GPBFieldDataTypeIsMessage(field)) {
 
  95       switch (field.fieldType) {
 
  96         case GPBFieldTypeSingle:
 
  97           if (GPBGetHasIvarField(msg, field)) {
 
  98             GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
 
  99             [todo addObject:fieldMessage];
 
 103         case GPBFieldTypeRepeated: {
 
 104           NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
 
 105           if (fieldMessages.count) {
 
 106             [todo addObjectsFromArray:fieldMessages];
 
 111         case GPBFieldTypeMap: {
 
 112           id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
 
 113           switch (field.mapKeyDataType) {
 
 114             case GPBDataTypeBool:
 
 115               [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 116                   BOOL key, id _Nonnull object, BOOL * _Nonnull stop) {
 
 117                 #pragma unused(key, stop)
 
 118                 [todo addObject:object];
 
 121             case GPBDataTypeFixed32:
 
 122             case GPBDataTypeUInt32:
 
 123               [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 124                   uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
 
 125                 #pragma unused(key, stop)
 
 126                 [todo addObject:object];
 
 129             case GPBDataTypeInt32:
 
 130             case GPBDataTypeSFixed32:
 
 131             case GPBDataTypeSInt32:
 
 132               [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 133                   int32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
 
 134                 #pragma unused(key, stop)
 
 135                 [todo addObject:object];
 
 138             case GPBDataTypeFixed64:
 
 139             case GPBDataTypeUInt64:
 
 140               [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 141                   uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
 
 142                 #pragma unused(key, stop)
 
 143                 [todo addObject:object];
 
 146             case GPBDataTypeInt64:
 
 147             case GPBDataTypeSFixed64:
 
 148             case GPBDataTypeSInt64:
 
 149               [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 150                   int64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
 
 151                 #pragma unused(key, stop)
 
 152                 [todo addObject:object];
 
 155             case GPBDataTypeString:
 
 156               [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
 
 157                   NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) {
 
 158                 #pragma unused(key, stop)
 
 159                 [todo addObject:obj];
 
 162             case GPBDataTypeFloat:
 
 163             case GPBDataTypeDouble:
 
 164             case GPBDataTypeEnum:
 
 165             case GPBDataTypeBytes:
 
 166             case GPBDataTypeGroup:
 
 167             case GPBDataTypeMessage:
 
 168               NSCAssert(NO, @"Aren't valid key types.");
 
 171         }  // switch(field.mapKeyDataType)
 
 172       }  // switch(field.fieldType)
 
 175     // Handle any extensions holding messages.
 
 176     for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) {
 
 177       if (!GPBDataTypeIsMessage(extension.dataType)) {
 
 180       if (extension.isRepeated) {
 
 181         NSArray *extMessages = [msg getExtension:extension];
 
 182         [todo addObjectsFromArray:extMessages];
 
 184         GPBMessage *extMessage = [msg getExtension:extension];
 
 185         [todo addObject:extMessage];
 
 187     }  // for(extensionsCurrentlySet)
 
 189   }  // while(todo.count)
 
 193 // -- About Version Checks --
 
 194 // There's actually 3 places these checks all come into play:
 
 195 // 1. When the generated source is compile into .o files, the header check
 
 196 //    happens. This is checking the protoc used matches the library being used
 
 197 //    when making the .o.
 
 198 // 2. Every place a generated proto header is included in a developer's code,
 
 199 //    the header check comes into play again. But this time it is checking that
 
 200 //    the current library headers being used still support/match the ones for
 
 201 //    the generated code.
 
 202 // 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is
 
 203 //    called from the generated code passing in values captured when the
 
 204 //    generated code's .o was made. This checks that at runtime the generated
 
 205 //    code and runtime library match.
 
 207 void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) {
 
 208   // NOTE: This is passing the value captured in the compiled code to check
 
 209   // against the values captured when the runtime support was compiled. This
 
 210   // ensures the library code isn't in a different framework/library that
 
 211   // was generated with a non matching version.
 
 212   if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) {
 
 213     // Library is too old for headers.
 
 214     [NSException raise:NSInternalInconsistencyException
 
 215                 format:@"Linked to ProtocolBuffer runtime version %d,"
 
 216                        @" but code compiled needing atleast %d!",
 
 217                        GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
 
 219   if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
 
 220     // Headers are too old for library.
 
 221     [NSException raise:NSInternalInconsistencyException
 
 222                 format:@"Proto generation source compiled against runtime"
 
 223                        @" version %d, but this version of the runtime only"
 
 224                        @" supports back to %d!",
 
 226                        GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
 
 230 // This api is no longer used for version checks. 30001 is the last version
 
 231 // using this old versioning model. When that support is removed, this function
 
 232 // can be removed (along with the declaration in GPBUtilities_PackagePrivate.h).
 
 233 void GPBCheckRuntimeVersionInternal(int32_t version) {
 
 234   GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001,
 
 235                            time_to_remove_this_old_version_shim);
 
 236   if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
 
 237     [NSException raise:NSInternalInconsistencyException
 
 238                 format:@"Linked to ProtocolBuffer runtime version %d,"
 
 239                        @" but code compiled with version %d!",
 
 240                        GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
 
 244 BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
 
 245   GPBDescriptor *descriptor = [self descriptor];
 
 246   GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
 
 247   return GPBMessageHasFieldSet(self, field);
 
 250 BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
 
 251   if (self == nil || field == nil) return NO;
 
 253   // Repeated/Map don't use the bit, they check the count.
 
 254   if (GPBFieldIsMapOrArray(field)) {
 
 255     // Array/map type doesn't matter, since GPB*Array/NSArray and
 
 256     // GPB*Dictionary/NSDictionary all support -count;
 
 257     NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
 
 258     return (arrayOrMap.count > 0);
 
 260     return GPBGetHasIvarField(self, field);
 
 264 void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
 
 265   // If not set, nothing to do.
 
 266   if (!GPBGetHasIvarField(self, field)) {
 
 270   if (GPBFieldStoresObject(field)) {
 
 271     // Object types are handled slightly differently, they need to be released.
 
 272     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 273     id *typePtr = (id *)&storage[field->description_->offset];
 
 277     // POD types just need to clear the has bit as the Get* method will
 
 278     // fetch the default when needed.
 
 280   GPBSetHasIvarField(self, field, NO);
 
 283 BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
 
 284   NSCAssert(self->messageStorage_ != NULL,
 
 285             @"%@: All messages should have storage (from init)",
 
 288     NSCAssert(fieldNumber != 0, @"Invalid field number.");
 
 289     BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
 
 292     NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
 
 293     uint32_t byteIndex = idx / 32;
 
 294     uint32_t bitMask = (1U << (idx % 32));
 
 296         (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
 
 301 uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
 
 302   NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.",
 
 304   uint32_t result = self->messageStorage_->_has_storage_[-idx];
 
 308 void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
 
 311     NSCAssert(fieldNumber != 0, @"Invalid field number.");
 
 312     uint32_t *has_storage = self->messageStorage_->_has_storage_;
 
 313     has_storage[-idx] = (value ? fieldNumber : 0);
 
 315     NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
 
 316     uint32_t *has_storage = self->messageStorage_->_has_storage_;
 
 317     uint32_t byte = idx / 32;
 
 318     uint32_t bitMask = (1U << (idx % 32));
 
 320       has_storage[byte] |= bitMask;
 
 322       has_storage[byte] &= ~bitMask;
 
 327 void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
 
 328                         int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
 
 329   uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
 
 330   if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
 
 331     // Do nothing/nothing set in the oneof.
 
 335   // Like GPBClearMessageField(), free the memory if an objecttype is set,
 
 336   // pod types don't need to do anything.
 
 337   GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
 
 339             @"%@: oneof set to something (%u) not in the oneof?",
 
 340             [self class], fieldNumberSet);
 
 341   if (fieldSet && GPBFieldStoresObject(fieldSet)) {
 
 342     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 343     id *typePtr = (id *)&storage[fieldSet->description_->offset];
 
 348   // Set to nothing stored in the oneof.
 
 349   // (field number doesn't matter since setting to nothing).
 
 350   GPBSetHasIvar(self, oneofHasIndex, 1, NO);
 
 353 #pragma mark - IVar accessors
 
 355 //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
 
 356 //%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
 
 357 //% TYPE$S            NAME$S       GPBFieldDescriptor *field) {
 
 358 //%#if defined(DEBUG) && DEBUG
 
 359 //%  NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 360 //%                                GPBDataType##NAME),
 
 361 //%            @"Attempting to get value of TYPE from field %@ "
 
 362 //%            @"of %@ which is of type %@.",
 
 363 //%            [self class], field.name,
 
 364 //%            TypeToString(GPBGetFieldDataType(field)));
 
 366 //%  if (GPBGetHasIvarField(self, field)) {
 
 367 //%    uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 368 //%    TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
 
 371 //%    return field.defaultValue.value##NAME;
 
 375 //%// Only exists for public api, no core code should use this.
 
 376 //%void GPBSetMessage##NAME##Field(GPBMessage *self,
 
 377 //%                   NAME$S     GPBFieldDescriptor *field,
 
 378 //%                   NAME$S     TYPE value) {
 
 379 //%  if (self == nil || field == nil) return;
 
 380 //%  GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 381 //%  GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
 
 384 //%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
 
 385 //%            NAME$S                     GPBFieldDescriptor *field,
 
 386 //%            NAME$S                     TYPE value,
 
 387 //%            NAME$S                     GPBFileSyntax syntax) {
 
 388 //%#if defined(DEBUG) && DEBUG
 
 389 //%  NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 390 //%                                GPBDataType##NAME),
 
 391 //%            @"Attempting to set field %@ of %@ which is of type %@ with "
 
 392 //%            @"value of type TYPE.",
 
 393 //%            [self class], field.name,
 
 394 //%            TypeToString(GPBGetFieldDataType(field)));
 
 396 //%  GPBOneofDescriptor *oneof = field->containingOneof_;
 
 398 //%    GPBMessageFieldDescription *fieldDesc = field->description_;
 
 399 //%    GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 401 //%#if defined(DEBUG) && DEBUG
 
 402 //%  NSCAssert(self->messageStorage_ != NULL,
 
 403 //%            @"%@: All messages should have storage (from init)",
 
 406 //%#if defined(__clang_analyzer__)
 
 407 //%  if (self->messageStorage_ == NULL) return;
 
 409 //%  uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 410 //%  TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
 
 411 //%  *typePtr = value;
 
 412 //%  // proto2: any value counts as having been set; proto3, it
 
 413 //%  // has to be a non zero value or be in a oneof.
 
 414 //%  BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
 415 //%                   || (value != (TYPE)0)
 
 416 //%                   || (field->containingOneof_ != NULL));
 
 417 //%  GPBSetHasIvarField(self, field, hasValue);
 
 418 //%  GPBBecomeVisibleToAutocreator(self);
 
 421 //%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
 
 422 //%// Only exists for public api, no core code should use this.
 
 423 //%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
 
 424 //% TYPE$S             NAME$S       GPBFieldDescriptor *field) {
 
 425 //%#if defined(DEBUG) && DEBUG
 
 426 //%  NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 427 //%                                GPBDataType##NAME),
 
 428 //%            @"Attempting to get value of TYPE from field %@ "
 
 429 //%            @"of %@ which is of type %@.",
 
 430 //%            [self class], field.name,
 
 431 //%            TypeToString(GPBGetFieldDataType(field)));
 
 433 //%  return (TYPE *)GPBGetObjectIvarWithField(self, field);
 
 436 //%// Only exists for public api, no core code should use this.
 
 437 //%void GPBSetMessage##NAME##Field(GPBMessage *self,
 
 438 //%                   NAME$S     GPBFieldDescriptor *field,
 
 439 //%                   NAME$S     TYPE *value) {
 
 440 //%#if defined(DEBUG) && DEBUG
 
 441 //%  NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 442 //%                                GPBDataType##NAME),
 
 443 //%            @"Attempting to set field %@ of %@ which is of type %@ with "
 
 444 //%            @"value of type TYPE.",
 
 445 //%            [self class], field.name,
 
 446 //%            TypeToString(GPBGetFieldDataType(field)));
 
 448 //%  GPBSetObjectIvarWithField(self, field, (id)value);
 
 452 // Object types are handled slightly differently, they need to be released
 
 455 void GPBSetAutocreatedRetainedObjectIvarWithField(
 
 456     GPBMessage *self, GPBFieldDescriptor *field,
 
 457     id __attribute__((ns_consumed)) value) {
 
 458   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 459   id *typePtr = (id *)&storage[field->description_->offset];
 
 460   NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
 
 464 void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
 
 465                                              GPBFieldDescriptor *field) {
 
 466   if (GPBGetHasIvarField(self, field)) {
 
 469   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 470   id *typePtr = (id *)&storage[field->description_->offset];
 
 471   GPBMessage *oldValue = *typePtr;
 
 473   GPBClearMessageAutocreator(oldValue);
 
 477 // This exists only for briging some aliased types, nothing else should use it.
 
 478 static void GPBSetObjectIvarWithField(GPBMessage *self,
 
 479                                       GPBFieldDescriptor *field, id value) {
 
 480   if (self == nil || field == nil) return;
 
 481   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 482   GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
 
 486 void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
 
 487                                        GPBFieldDescriptor *field, id value,
 
 488                                        GPBFileSyntax syntax) {
 
 489   GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
 
 493 void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
 
 494                                                GPBFieldDescriptor *field,
 
 495                                                id value, GPBFileSyntax syntax) {
 
 496   NSCAssert(self->messageStorage_ != NULL,
 
 497             @"%@: All messages should have storage (from init)",
 
 499 #if defined(__clang_analyzer__)
 
 500   if (self->messageStorage_ == NULL) return;
 
 502   GPBDataType fieldType = GPBGetFieldDataType(field);
 
 503   BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
 
 504   BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
 
 505 #if defined(DEBUG) && DEBUG
 
 506   if (value == nil && !isMapOrArray && !fieldIsMessage &&
 
 507       field.hasDefaultValue) {
 
 508     // Setting a message to nil is an obvious way to "clear" the value
 
 509     // as there is no way to set a non-empty default value for messages.
 
 511     // For Strings and Bytes that have default values set it is not clear what
 
 512     // should be done when their value is set to nil. Is the intention just to
 
 513     // clear the set value and reset to default, or is the intention to set the
 
 514     // value to the empty string/data? Arguments can be made for both cases.
 
 515     // 'nil' has been abused as a replacement for an empty string/data in ObjC.
 
 516     // We decided to be consistent with all "object" types and clear the has
 
 517     // field, and fall back on the default value. The warning below will only
 
 518     // appear in debug, but the could should be changed so the intention is
 
 520     NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_);
 
 521     NSString *propName = field.name;
 
 522     NSString *className = self.descriptor.name;
 
 523     NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
 
 524           @"default values. Please use '%@.%@ = %@' if you want to set it to "
 
 525           @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
 
 526           @"'%@'. Defaulting to resetting default value.",
 
 527           className, propName, className, propName,
 
 528           (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
 
 529           className, hasSel, field.defaultValue.valueString);
 
 530     // Note: valueString, depending on the type, it could easily be
 
 531     // valueData/valueMessage.
 
 535     // Non repeated/map can be in an oneof, clear any existing value from the
 
 537     GPBOneofDescriptor *oneof = field->containingOneof_;
 
 539       GPBMessageFieldDescription *fieldDesc = field->description_;
 
 540       GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 542     // Clear "has" if they are being set to nil.
 
 543     BOOL setHasValue = (value != nil);
 
 544     // Under proto3, Bytes & String fields get cleared by resetting them to
 
 545     // their default (empty) values, so if they are set to something of length
 
 546     // zero, they are being cleared.
 
 547     if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
 
 548         ([value length] == 0)) {
 
 549       // Except, if the field was in a oneof, then it still gets recorded as
 
 550       // having been set so the state of the oneof can be serialized back out.
 
 555         NSCAssert(value != nil, @"Should never be setting has for nil");
 
 557         // The value passed in was retained, it must be released since we
 
 558         // aren't saving anything in the field.
 
 563     GPBSetHasIvarField(self, field, setHasValue);
 
 565   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 566   id *typePtr = (id *)&storage[field->description_->offset];
 
 568   id oldValue = *typePtr;
 
 574       if (field.fieldType == GPBFieldTypeRepeated) {
 
 575         // If the old array was autocreated by us, then clear it.
 
 576         if (GPBDataTypeIsObject(fieldType)) {
 
 577           if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) {
 
 578             GPBAutocreatedArray *autoArray = oldValue;
 
 579             if (autoArray->_autocreator == self) {
 
 580               autoArray->_autocreator = nil;
 
 584           // Type doesn't matter, it is a GPB*Array.
 
 585           GPBInt32Array *gpbArray = oldValue;
 
 586           if (gpbArray->_autocreator == self) {
 
 587             gpbArray->_autocreator = nil;
 
 590       } else { // GPBFieldTypeMap
 
 591         // If the old map was autocreated by us, then clear it.
 
 592         if ((field.mapKeyDataType == GPBDataTypeString) &&
 
 593             GPBDataTypeIsObject(fieldType)) {
 
 594           if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
 
 595             GPBAutocreatedDictionary *autoDict = oldValue;
 
 596             if (autoDict->_autocreator == self) {
 
 597               autoDict->_autocreator = nil;
 
 601           // Type doesn't matter, it is a GPB*Dictionary.
 
 602           GPBInt32Int32Dictionary *gpbDict = oldValue;
 
 603           if (gpbDict->_autocreator == self) {
 
 604             gpbDict->_autocreator = nil;
 
 608     } else if (fieldIsMessage) {
 
 609       // If the old message value was autocreated by us, then clear it.
 
 610       GPBMessage *oldMessageValue = oldValue;
 
 611       if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
 
 612         GPBClearMessageAutocreator(oldMessageValue);
 
 618   GPBBecomeVisibleToAutocreator(self);
 
 621 id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
 
 622                                          GPBFieldDescriptor *field) {
 
 623   if (self->messageStorage_ == nil) {
 
 626   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 627   id *typePtr = (id *)&storage[field->description_->offset];
 
 631 // Only exists for public api, no core code should use this.
 
 632 int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
 
 633   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 634   return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
 
 637 int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
 
 638                                         GPBFieldDescriptor *field,
 
 639                                         GPBFileSyntax syntax) {
 
 640 #if defined(DEBUG) && DEBUG
 
 641   NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
 
 642             @"Attempting to get value of type Enum from field %@ "
 
 643             @"of %@ which is of type %@.",
 
 644             [self class], field.name,
 
 645             TypeToString(GPBGetFieldDataType(field)));
 
 647   int32_t result = GPBGetMessageInt32Field(self, field);
 
 648   // If this is presevering unknown enums, make sure the value is valid before
 
 650   if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
 
 651       ![field isValidEnumValue:result]) {
 
 652     result = kGPBUnrecognizedEnumeratorValue;
 
 657 // Only exists for public api, no core code should use this.
 
 658 void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
 
 660   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 661   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 
 664 void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
 
 665                                      GPBFieldDescriptor *field, int32_t value,
 
 666                                      GPBFileSyntax syntax) {
 
 667 #if defined(DEBUG) && DEBUG
 
 668   NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
 
 669             @"Attempting to set field %@ of %@ which is of type %@ with "
 
 670             @"value of type Enum.",
 
 671             [self class], field.name,
 
 672             TypeToString(GPBGetFieldDataType(field)));
 
 674   // Don't allow in unknown values.  Proto3 can use the Raw method.
 
 675   if (![field isValidEnumValue:value]) {
 
 676     [NSException raise:NSInvalidArgumentException
 
 677                 format:@"%@.%@: Attempt to set an unknown enum value (%d)",
 
 678                        [self class], field.name, value];
 
 680   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 
 683 // Only exists for public api, no core code should use this.
 
 684 int32_t GPBGetMessageRawEnumField(GPBMessage *self,
 
 685                                   GPBFieldDescriptor *field) {
 
 686   int32_t result = GPBGetMessageInt32Field(self, field);
 
 690 // Only exists for public api, no core code should use this.
 
 691 void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
 
 693   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 694   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 
 697 BOOL GPBGetMessageBoolField(GPBMessage *self,
 
 698                             GPBFieldDescriptor *field) {
 
 699 #if defined(DEBUG) && DEBUG
 
 700   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
 
 701             @"Attempting to get value of type bool from field %@ "
 
 702             @"of %@ which is of type %@.",
 
 703             [self class], field.name,
 
 704             TypeToString(GPBGetFieldDataType(field)));
 
 706   if (GPBGetHasIvarField(self, field)) {
 
 707     // Bools are stored in the has bits to avoid needing explicit space in the
 
 708     // storage structure.
 
 709     // (the field number passed to the HasIvar helper doesn't really matter
 
 710     // since the offset is never negative)
 
 711     GPBMessageFieldDescription *fieldDesc = field->description_;
 
 712     return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number);
 
 714     return field.defaultValue.valueBool;
 
 718 // Only exists for public api, no core code should use this.
 
 719 void GPBSetMessageBoolField(GPBMessage *self,
 
 720                             GPBFieldDescriptor *field,
 
 722   if (self == nil || field == nil) return;
 
 723   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 724   GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
 
 727 void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
 
 728                                      GPBFieldDescriptor *field,
 
 730                                      GPBFileSyntax syntax) {
 
 731 #if defined(DEBUG) && DEBUG
 
 732   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
 
 733             @"Attempting to set field %@ of %@ which is of type %@ with "
 
 734             @"value of type bool.",
 
 735             [self class], field.name,
 
 736             TypeToString(GPBGetFieldDataType(field)));
 
 738   GPBMessageFieldDescription *fieldDesc = field->description_;
 
 739   GPBOneofDescriptor *oneof = field->containingOneof_;
 
 741     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 744   // Bools are stored in the has bits to avoid needing explicit space in the
 
 745   // storage structure.
 
 746   // (the field number passed to the HasIvar helper doesn't really matter since
 
 747   // the offset is never negative)
 
 748   GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
 
 750   // proto2: any value counts as having been set; proto3, it
 
 751   // has to be a non zero value or be in a oneof.
 
 752   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
 753                    || (value != (BOOL)0)
 
 754                    || (field->containingOneof_ != NULL));
 
 755   GPBSetHasIvarField(self, field, hasValue);
 
 756   GPBBecomeVisibleToAutocreator(self);
 
 759 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
 
 760 // This block of code is generated, do not edit it directly.
 
 762 int32_t GPBGetMessageInt32Field(GPBMessage *self,
 
 763                                 GPBFieldDescriptor *field) {
 
 764 #if defined(DEBUG) && DEBUG
 
 765   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 767             @"Attempting to get value of int32_t from field %@ "
 
 768             @"of %@ which is of type %@.",
 
 769             [self class], field.name,
 
 770             TypeToString(GPBGetFieldDataType(field)));
 
 772   if (GPBGetHasIvarField(self, field)) {
 
 773     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 774     int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
 
 777     return field.defaultValue.valueInt32;
 
 781 // Only exists for public api, no core code should use this.
 
 782 void GPBSetMessageInt32Field(GPBMessage *self,
 
 783                              GPBFieldDescriptor *field,
 
 785   if (self == nil || field == nil) return;
 
 786   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 787   GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
 
 790 void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
 
 791                                       GPBFieldDescriptor *field,
 
 793                                       GPBFileSyntax syntax) {
 
 794 #if defined(DEBUG) && DEBUG
 
 795   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 797             @"Attempting to set field %@ of %@ which is of type %@ with "
 
 798             @"value of type int32_t.",
 
 799             [self class], field.name,
 
 800             TypeToString(GPBGetFieldDataType(field)));
 
 802   GPBOneofDescriptor *oneof = field->containingOneof_;
 
 804     GPBMessageFieldDescription *fieldDesc = field->description_;
 
 805     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 807 #if defined(DEBUG) && DEBUG
 
 808   NSCAssert(self->messageStorage_ != NULL,
 
 809             @"%@: All messages should have storage (from init)",
 
 812 #if defined(__clang_analyzer__)
 
 813   if (self->messageStorage_ == NULL) return;
 
 815   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 816   int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
 
 818   // proto2: any value counts as having been set; proto3, it
 
 819   // has to be a non zero value or be in a oneof.
 
 820   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
 821                    || (value != (int32_t)0)
 
 822                    || (field->containingOneof_ != NULL));
 
 823   GPBSetHasIvarField(self, field, hasValue);
 
 824   GPBBecomeVisibleToAutocreator(self);
 
 827 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
 
 828 // This block of code is generated, do not edit it directly.
 
 830 uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
 
 831                                   GPBFieldDescriptor *field) {
 
 832 #if defined(DEBUG) && DEBUG
 
 833   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 835             @"Attempting to get value of uint32_t from field %@ "
 
 836             @"of %@ which is of type %@.",
 
 837             [self class], field.name,
 
 838             TypeToString(GPBGetFieldDataType(field)));
 
 840   if (GPBGetHasIvarField(self, field)) {
 
 841     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 842     uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
 
 845     return field.defaultValue.valueUInt32;
 
 849 // Only exists for public api, no core code should use this.
 
 850 void GPBSetMessageUInt32Field(GPBMessage *self,
 
 851                               GPBFieldDescriptor *field,
 
 853   if (self == nil || field == nil) return;
 
 854   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 855   GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
 
 858 void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
 
 859                                        GPBFieldDescriptor *field,
 
 861                                        GPBFileSyntax syntax) {
 
 862 #if defined(DEBUG) && DEBUG
 
 863   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 865             @"Attempting to set field %@ of %@ which is of type %@ with "
 
 866             @"value of type uint32_t.",
 
 867             [self class], field.name,
 
 868             TypeToString(GPBGetFieldDataType(field)));
 
 870   GPBOneofDescriptor *oneof = field->containingOneof_;
 
 872     GPBMessageFieldDescription *fieldDesc = field->description_;
 
 873     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 875 #if defined(DEBUG) && DEBUG
 
 876   NSCAssert(self->messageStorage_ != NULL,
 
 877             @"%@: All messages should have storage (from init)",
 
 880 #if defined(__clang_analyzer__)
 
 881   if (self->messageStorage_ == NULL) return;
 
 883   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 884   uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
 
 886   // proto2: any value counts as having been set; proto3, it
 
 887   // has to be a non zero value or be in a oneof.
 
 888   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
 889                    || (value != (uint32_t)0)
 
 890                    || (field->containingOneof_ != NULL));
 
 891   GPBSetHasIvarField(self, field, hasValue);
 
 892   GPBBecomeVisibleToAutocreator(self);
 
 895 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
 
 896 // This block of code is generated, do not edit it directly.
 
 898 int64_t GPBGetMessageInt64Field(GPBMessage *self,
 
 899                                 GPBFieldDescriptor *field) {
 
 900 #if defined(DEBUG) && DEBUG
 
 901   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 903             @"Attempting to get value of int64_t from field %@ "
 
 904             @"of %@ which is of type %@.",
 
 905             [self class], field.name,
 
 906             TypeToString(GPBGetFieldDataType(field)));
 
 908   if (GPBGetHasIvarField(self, field)) {
 
 909     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 910     int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
 
 913     return field.defaultValue.valueInt64;
 
 917 // Only exists for public api, no core code should use this.
 
 918 void GPBSetMessageInt64Field(GPBMessage *self,
 
 919                              GPBFieldDescriptor *field,
 
 921   if (self == nil || field == nil) return;
 
 922   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 923   GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
 
 926 void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
 
 927                                       GPBFieldDescriptor *field,
 
 929                                       GPBFileSyntax syntax) {
 
 930 #if defined(DEBUG) && DEBUG
 
 931   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 933             @"Attempting to set field %@ of %@ which is of type %@ with "
 
 934             @"value of type int64_t.",
 
 935             [self class], field.name,
 
 936             TypeToString(GPBGetFieldDataType(field)));
 
 938   GPBOneofDescriptor *oneof = field->containingOneof_;
 
 940     GPBMessageFieldDescription *fieldDesc = field->description_;
 
 941     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
 943 #if defined(DEBUG) && DEBUG
 
 944   NSCAssert(self->messageStorage_ != NULL,
 
 945             @"%@: All messages should have storage (from init)",
 
 948 #if defined(__clang_analyzer__)
 
 949   if (self->messageStorage_ == NULL) return;
 
 951   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 952   int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
 
 954   // proto2: any value counts as having been set; proto3, it
 
 955   // has to be a non zero value or be in a oneof.
 
 956   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
 957                    || (value != (int64_t)0)
 
 958                    || (field->containingOneof_ != NULL));
 
 959   GPBSetHasIvarField(self, field, hasValue);
 
 960   GPBBecomeVisibleToAutocreator(self);
 
 963 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
 
 964 // This block of code is generated, do not edit it directly.
 
 966 uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
 
 967                                   GPBFieldDescriptor *field) {
 
 968 #if defined(DEBUG) && DEBUG
 
 969   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
 971             @"Attempting to get value of uint64_t from field %@ "
 
 972             @"of %@ which is of type %@.",
 
 973             [self class], field.name,
 
 974             TypeToString(GPBGetFieldDataType(field)));
 
 976   if (GPBGetHasIvarField(self, field)) {
 
 977     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
 978     uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
 
 981     return field.defaultValue.valueUInt64;
 
 985 // Only exists for public api, no core code should use this.
 
 986 void GPBSetMessageUInt64Field(GPBMessage *self,
 
 987                               GPBFieldDescriptor *field,
 
 989   if (self == nil || field == nil) return;
 
 990   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
 991   GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
 
 994 void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
 
 995                                        GPBFieldDescriptor *field,
 
 997                                        GPBFileSyntax syntax) {
 
 998 #if defined(DEBUG) && DEBUG
 
 999   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1001             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1002             @"value of type uint64_t.",
 
1003             [self class], field.name,
 
1004             TypeToString(GPBGetFieldDataType(field)));
 
1006   GPBOneofDescriptor *oneof = field->containingOneof_;
 
1008     GPBMessageFieldDescription *fieldDesc = field->description_;
 
1009     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
1011 #if defined(DEBUG) && DEBUG
 
1012   NSCAssert(self->messageStorage_ != NULL,
 
1013             @"%@: All messages should have storage (from init)",
 
1016 #if defined(__clang_analyzer__)
 
1017   if (self->messageStorage_ == NULL) return;
 
1019   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
1020   uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
 
1022   // proto2: any value counts as having been set; proto3, it
 
1023   // has to be a non zero value or be in a oneof.
 
1024   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
1025                    || (value != (uint64_t)0)
 
1026                    || (field->containingOneof_ != NULL));
 
1027   GPBSetHasIvarField(self, field, hasValue);
 
1028   GPBBecomeVisibleToAutocreator(self);
 
1031 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
 
1032 // This block of code is generated, do not edit it directly.
 
1034 float GPBGetMessageFloatField(GPBMessage *self,
 
1035                               GPBFieldDescriptor *field) {
 
1036 #if defined(DEBUG) && DEBUG
 
1037   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1039             @"Attempting to get value of float from field %@ "
 
1040             @"of %@ which is of type %@.",
 
1041             [self class], field.name,
 
1042             TypeToString(GPBGetFieldDataType(field)));
 
1044   if (GPBGetHasIvarField(self, field)) {
 
1045     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
1046     float *typePtr = (float *)&storage[field->description_->offset];
 
1049     return field.defaultValue.valueFloat;
 
1053 // Only exists for public api, no core code should use this.
 
1054 void GPBSetMessageFloatField(GPBMessage *self,
 
1055                              GPBFieldDescriptor *field,
 
1057   if (self == nil || field == nil) return;
 
1058   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
1059   GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
 
1062 void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
 
1063                                       GPBFieldDescriptor *field,
 
1065                                       GPBFileSyntax syntax) {
 
1066 #if defined(DEBUG) && DEBUG
 
1067   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1069             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1070             @"value of type float.",
 
1071             [self class], field.name,
 
1072             TypeToString(GPBGetFieldDataType(field)));
 
1074   GPBOneofDescriptor *oneof = field->containingOneof_;
 
1076     GPBMessageFieldDescription *fieldDesc = field->description_;
 
1077     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
1079 #if defined(DEBUG) && DEBUG
 
1080   NSCAssert(self->messageStorage_ != NULL,
 
1081             @"%@: All messages should have storage (from init)",
 
1084 #if defined(__clang_analyzer__)
 
1085   if (self->messageStorage_ == NULL) return;
 
1087   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
1088   float *typePtr = (float *)&storage[field->description_->offset];
 
1090   // proto2: any value counts as having been set; proto3, it
 
1091   // has to be a non zero value or be in a oneof.
 
1092   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
1093                    || (value != (float)0)
 
1094                    || (field->containingOneof_ != NULL));
 
1095   GPBSetHasIvarField(self, field, hasValue);
 
1096   GPBBecomeVisibleToAutocreator(self);
 
1099 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
 
1100 // This block of code is generated, do not edit it directly.
 
1102 double GPBGetMessageDoubleField(GPBMessage *self,
 
1103                                 GPBFieldDescriptor *field) {
 
1104 #if defined(DEBUG) && DEBUG
 
1105   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1107             @"Attempting to get value of double from field %@ "
 
1108             @"of %@ which is of type %@.",
 
1109             [self class], field.name,
 
1110             TypeToString(GPBGetFieldDataType(field)));
 
1112   if (GPBGetHasIvarField(self, field)) {
 
1113     uint8_t *storage = (uint8_t *)self->messageStorage_;
 
1114     double *typePtr = (double *)&storage[field->description_->offset];
 
1117     return field.defaultValue.valueDouble;
 
1121 // Only exists for public api, no core code should use this.
 
1122 void GPBSetMessageDoubleField(GPBMessage *self,
 
1123                               GPBFieldDescriptor *field,
 
1125   if (self == nil || field == nil) return;
 
1126   GPBFileSyntax syntax = [self descriptor].file.syntax;
 
1127   GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
 
1130 void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
 
1131                                        GPBFieldDescriptor *field,
 
1133                                        GPBFileSyntax syntax) {
 
1134 #if defined(DEBUG) && DEBUG
 
1135   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1137             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1138             @"value of type double.",
 
1139             [self class], field.name,
 
1140             TypeToString(GPBGetFieldDataType(field)));
 
1142   GPBOneofDescriptor *oneof = field->containingOneof_;
 
1144     GPBMessageFieldDescription *fieldDesc = field->description_;
 
1145     GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
 
1147 #if defined(DEBUG) && DEBUG
 
1148   NSCAssert(self->messageStorage_ != NULL,
 
1149             @"%@: All messages should have storage (from init)",
 
1152 #if defined(__clang_analyzer__)
 
1153   if (self->messageStorage_ == NULL) return;
 
1155   uint8_t *storage = (uint8_t *)self->messageStorage_;
 
1156   double *typePtr = (double *)&storage[field->description_->offset];
 
1158   // proto2: any value counts as having been set; proto3, it
 
1159   // has to be a non zero value or be in a oneof.
 
1160   BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
 
1161                    || (value != (double)0)
 
1162                    || (field->containingOneof_ != NULL));
 
1163   GPBSetHasIvarField(self, field, hasValue);
 
1164   GPBBecomeVisibleToAutocreator(self);
 
1167 //%PDDM-EXPAND-END (6 expansions)
 
1169 // Aliases are function calls that are virtually the same.
 
1171 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString)
 
1172 // This block of code is generated, do not edit it directly.
 
1174 // Only exists for public api, no core code should use this.
 
1175 NSString *GPBGetMessageStringField(GPBMessage *self,
 
1176                                    GPBFieldDescriptor *field) {
 
1177 #if defined(DEBUG) && DEBUG
 
1178   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1180             @"Attempting to get value of NSString from field %@ "
 
1181             @"of %@ which is of type %@.",
 
1182             [self class], field.name,
 
1183             TypeToString(GPBGetFieldDataType(field)));
 
1185   return (NSString *)GPBGetObjectIvarWithField(self, field);
 
1188 // Only exists for public api, no core code should use this.
 
1189 void GPBSetMessageStringField(GPBMessage *self,
 
1190                               GPBFieldDescriptor *field,
 
1192 #if defined(DEBUG) && DEBUG
 
1193   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1195             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1196             @"value of type NSString.",
 
1197             [self class], field.name,
 
1198             TypeToString(GPBGetFieldDataType(field)));
 
1200   GPBSetObjectIvarWithField(self, field, (id)value);
 
1203 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData)
 
1204 // This block of code is generated, do not edit it directly.
 
1206 // Only exists for public api, no core code should use this.
 
1207 NSData *GPBGetMessageBytesField(GPBMessage *self,
 
1208                                 GPBFieldDescriptor *field) {
 
1209 #if defined(DEBUG) && DEBUG
 
1210   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1212             @"Attempting to get value of NSData from field %@ "
 
1213             @"of %@ which is of type %@.",
 
1214             [self class], field.name,
 
1215             TypeToString(GPBGetFieldDataType(field)));
 
1217   return (NSData *)GPBGetObjectIvarWithField(self, field);
 
1220 // Only exists for public api, no core code should use this.
 
1221 void GPBSetMessageBytesField(GPBMessage *self,
 
1222                              GPBFieldDescriptor *field,
 
1224 #if defined(DEBUG) && DEBUG
 
1225   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1227             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1228             @"value of type NSData.",
 
1229             [self class], field.name,
 
1230             TypeToString(GPBGetFieldDataType(field)));
 
1232   GPBSetObjectIvarWithField(self, field, (id)value);
 
1235 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
 
1236 // This block of code is generated, do not edit it directly.
 
1238 // Only exists for public api, no core code should use this.
 
1239 GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
 
1240                                       GPBFieldDescriptor *field) {
 
1241 #if defined(DEBUG) && DEBUG
 
1242   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1243                                 GPBDataTypeMessage),
 
1244             @"Attempting to get value of GPBMessage from field %@ "
 
1245             @"of %@ which is of type %@.",
 
1246             [self class], field.name,
 
1247             TypeToString(GPBGetFieldDataType(field)));
 
1249   return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
 
1252 // Only exists for public api, no core code should use this.
 
1253 void GPBSetMessageMessageField(GPBMessage *self,
 
1254                                GPBFieldDescriptor *field,
 
1255                                GPBMessage *value) {
 
1256 #if defined(DEBUG) && DEBUG
 
1257   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1258                                 GPBDataTypeMessage),
 
1259             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1260             @"value of type GPBMessage.",
 
1261             [self class], field.name,
 
1262             TypeToString(GPBGetFieldDataType(field)));
 
1264   GPBSetObjectIvarWithField(self, field, (id)value);
 
1267 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
 
1268 // This block of code is generated, do not edit it directly.
 
1270 // Only exists for public api, no core code should use this.
 
1271 GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
 
1272                                     GPBFieldDescriptor *field) {
 
1273 #if defined(DEBUG) && DEBUG
 
1274   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1276             @"Attempting to get value of GPBMessage from field %@ "
 
1277             @"of %@ which is of type %@.",
 
1278             [self class], field.name,
 
1279             TypeToString(GPBGetFieldDataType(field)));
 
1281   return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
 
1284 // Only exists for public api, no core code should use this.
 
1285 void GPBSetMessageGroupField(GPBMessage *self,
 
1286                              GPBFieldDescriptor *field,
 
1287                              GPBMessage *value) {
 
1288 #if defined(DEBUG) && DEBUG
 
1289   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
 
1291             @"Attempting to set field %@ of %@ which is of type %@ with "
 
1292             @"value of type GPBMessage.",
 
1293             [self class], field.name,
 
1294             TypeToString(GPBGetFieldDataType(field)));
 
1296   GPBSetObjectIvarWithField(self, field, (id)value);
 
1299 //%PDDM-EXPAND-END (4 expansions)
 
1301 // GPBGetMessageRepeatedField is defined in GPBMessage.m
 
1303 // Only exists for public api, no core code should use this.
 
1304 void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
 
1305 #if defined(DEBUG) && DEBUG
 
1306   if (field.fieldType != GPBFieldTypeRepeated) {
 
1307     [NSException raise:NSInvalidArgumentException
 
1308                 format:@"%@.%@ is not a repeated field.",
 
1309                        [self class], field.name];
 
1311   Class expectedClass = Nil;
 
1312   switch (GPBGetFieldDataType(field)) {
 
1313     case GPBDataTypeBool:
 
1314       expectedClass = [GPBBoolArray class];
 
1316     case GPBDataTypeSFixed32:
 
1317     case GPBDataTypeInt32:
 
1318     case GPBDataTypeSInt32:
 
1319       expectedClass = [GPBInt32Array class];
 
1321     case GPBDataTypeFixed32:
 
1322     case GPBDataTypeUInt32:
 
1323       expectedClass = [GPBUInt32Array class];
 
1325     case GPBDataTypeSFixed64:
 
1326     case GPBDataTypeInt64:
 
1327     case GPBDataTypeSInt64:
 
1328       expectedClass = [GPBInt64Array class];
 
1330     case GPBDataTypeFixed64:
 
1331     case GPBDataTypeUInt64:
 
1332       expectedClass = [GPBUInt64Array class];
 
1334     case GPBDataTypeFloat:
 
1335       expectedClass = [GPBFloatArray class];
 
1337     case GPBDataTypeDouble:
 
1338       expectedClass = [GPBDoubleArray class];
 
1340     case GPBDataTypeBytes:
 
1341     case GPBDataTypeString:
 
1342     case GPBDataTypeMessage:
 
1343     case GPBDataTypeGroup:
 
1344       expectedClass = [NSMutableArray class];
 
1346     case GPBDataTypeEnum:
 
1347       expectedClass = [GPBEnumArray class];
 
1350   if (array && ![array isKindOfClass:expectedClass]) {
 
1351     [NSException raise:NSInvalidArgumentException
 
1352                 format:@"%@.%@: Expected %@ object, got %@.",
 
1353                        [self class], field.name, expectedClass, [array class]];
 
1356   GPBSetObjectIvarWithField(self, field, array);
 
1359 static GPBDataType BaseDataType(GPBDataType type) {
 
1361     case GPBDataTypeSFixed32:
 
1362     case GPBDataTypeInt32:
 
1363     case GPBDataTypeSInt32:
 
1364     case GPBDataTypeEnum:
 
1365       return GPBDataTypeInt32;
 
1366     case GPBDataTypeFixed32:
 
1367     case GPBDataTypeUInt32:
 
1368       return GPBDataTypeUInt32;
 
1369     case GPBDataTypeSFixed64:
 
1370     case GPBDataTypeInt64:
 
1371     case GPBDataTypeSInt64:
 
1372       return GPBDataTypeInt64;
 
1373     case GPBDataTypeFixed64:
 
1374     case GPBDataTypeUInt64:
 
1375       return GPBDataTypeUInt64;
 
1376     case GPBDataTypeMessage:
 
1377     case GPBDataTypeGroup:
 
1378       return GPBDataTypeMessage;
 
1379     case GPBDataTypeBool:
 
1380     case GPBDataTypeFloat:
 
1381     case GPBDataTypeDouble:
 
1382     case GPBDataTypeBytes:
 
1383     case GPBDataTypeString:
 
1388 static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) {
 
1389   return BaseDataType(type1) == BaseDataType(type2);
 
1392 static NSString *TypeToString(GPBDataType dataType) {
 
1394     case GPBDataTypeBool:
 
1396     case GPBDataTypeSFixed32:
 
1397     case GPBDataTypeInt32:
 
1398     case GPBDataTypeSInt32:
 
1400     case GPBDataTypeFixed32:
 
1401     case GPBDataTypeUInt32:
 
1403     case GPBDataTypeSFixed64:
 
1404     case GPBDataTypeInt64:
 
1405     case GPBDataTypeSInt64:
 
1407     case GPBDataTypeFixed64:
 
1408     case GPBDataTypeUInt64:
 
1410     case GPBDataTypeFloat:
 
1412     case GPBDataTypeDouble:
 
1414     case GPBDataTypeBytes:
 
1415     case GPBDataTypeString:
 
1416     case GPBDataTypeMessage:
 
1417     case GPBDataTypeGroup:
 
1419     case GPBDataTypeEnum:
 
1424 // GPBGetMessageMapField is defined in GPBMessage.m
 
1426 // Only exists for public api, no core code should use this.
 
1427 void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
 
1429 #if defined(DEBUG) && DEBUG
 
1430   if (field.fieldType != GPBFieldTypeMap) {
 
1431     [NSException raise:NSInvalidArgumentException
 
1432                 format:@"%@.%@ is not a map<> field.",
 
1433                        [self class], field.name];
 
1436     GPBDataType keyDataType = field.mapKeyDataType;
 
1437     GPBDataType valueDataType = GPBGetFieldDataType(field);
 
1438     NSString *keyStr = TypeToString(keyDataType);
 
1439     NSString *valueStr = TypeToString(valueDataType);
 
1440     if (keyDataType == GPBDataTypeString) {
 
1443     Class expectedClass = Nil;
 
1444     if ((keyDataType == GPBDataTypeString) &&
 
1445         GPBDataTypeIsObject(valueDataType)) {
 
1446       expectedClass = [NSMutableDictionary class];
 
1448       NSString *className =
 
1449           [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
 
1450       expectedClass = NSClassFromString(className);
 
1451       NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
 
1453     if (![dictionary isKindOfClass:expectedClass]) {
 
1454       [NSException raise:NSInvalidArgumentException
 
1455                   format:@"%@.%@: Expected %@ object, got %@.",
 
1456                          [self class], field.name, expectedClass,
 
1457                          [dictionary class]];
 
1461   GPBSetObjectIvarWithField(self, field, dictionary);
 
1464 #pragma mark - Misc Dynamic Runtime Utils
 
1466 const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
 
1467   Protocol *protocol =
 
1468       objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
 
1469   NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol");
 
1470   struct objc_method_description description =
 
1471       protocol_getMethodDescription(protocol, selector, NO, instanceSel);
 
1472   NSCAssert(description.name != Nil && description.types != nil,
 
1473             @"Missing method for selector %@", NSStringFromSelector(selector));
 
1474   return description.types;
 
1477 #pragma mark - Text Format Support
 
1479 static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
 
1480   [destStr appendString:@"\""];
 
1481   NSUInteger len = [toPrint length];
 
1482   for (NSUInteger i = 0; i < len; ++i) {
 
1483     unichar aChar = [toPrint characterAtIndex:i];
 
1485       case '\n': [destStr appendString:@"\\n"];  break;
 
1486       case '\r': [destStr appendString:@"\\r"];  break;
 
1487       case '\t': [destStr appendString:@"\\t"];  break;
 
1488       case '\"': [destStr appendString:@"\\\""]; break;
 
1489       case '\'': [destStr appendString:@"\\\'"]; break;
 
1490       case '\\': [destStr appendString:@"\\\\"]; break;
 
1492         // This differs slightly from the C++ code in that the C++ doesn't
 
1493         // generate UTF8; it looks at the string in UTF8, but escapes every
 
1496           [destStr appendFormat:@"\\%d%d%d",
 
1497                                 (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
 
1499           [destStr appendFormat:@"%C", aChar];
 
1504   [destStr appendString:@"\""];
 
1507 static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
 
1508   const char *src = (const char *)[buffer bytes];
 
1509   size_t srcLen = [buffer length];
 
1510   [destStr appendString:@"\""];
 
1511   for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
 
1513       case '\n': [destStr appendString:@"\\n"];  break;
 
1514       case '\r': [destStr appendString:@"\\r"];  break;
 
1515       case '\t': [destStr appendString:@"\\t"];  break;
 
1516       case '\"': [destStr appendString:@"\\\""]; break;
 
1517       case '\'': [destStr appendString:@"\\\'"]; break;
 
1518       case '\\': [destStr appendString:@"\\\\"]; break;
 
1520         if (isprint(*src)) {
 
1521           [destStr appendFormat:@"%c", *src];
 
1523           // NOTE: doing hex means you have to worry about the letter after
 
1524           // the hex being another hex char and forcing that to be escaped, so
 
1525           // use octal to keep it simple.
 
1526           [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
 
1531   [destStr appendString:@"\""];
 
1534 static void AppendTextFormatForMapMessageField(
 
1535     id map, GPBFieldDescriptor *field, NSMutableString *toStr,
 
1536     NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
 
1537   GPBDataType keyDataType = field.mapKeyDataType;
 
1538   GPBDataType valueDataType = GPBGetFieldDataType(field);
 
1539   BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
 
1541   NSString *msgStartFirst =
 
1542       [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
 
1543   NSString *msgStart =
 
1544       [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
 
1545   NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
 
1547   NSString *keyLine = [NSString stringWithFormat:@"%@  key: ", lineIndent];
 
1548   NSString *valueLine = [NSString stringWithFormat:@"%@  value%s ", lineIndent,
 
1549                                                    (isMessageValue ? "" : ":")];
 
1551   __block BOOL isFirst = YES;
 
1553   if ((keyDataType == GPBDataTypeString) &&
 
1554       GPBDataTypeIsObject(valueDataType)) {
 
1555     // map is an NSDictionary.
 
1556     NSDictionary *dict = map;
 
1557     [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
 
1558       #pragma unused(stop)
 
1559       [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
 
1562       [toStr appendString:keyLine];
 
1563       AppendStringEscaped(key, toStr);
 
1564       [toStr appendString:@"\n"];
 
1566       [toStr appendString:valueLine];
 
1567 #pragma clang diagnostic push
 
1568 #pragma clang diagnostic ignored "-Wswitch-enum"
 
1569       switch (valueDataType) {
 
1570         case GPBDataTypeString:
 
1571           AppendStringEscaped(value, toStr);
 
1574         case GPBDataTypeBytes:
 
1575           AppendBufferAsString(value, toStr);
 
1578         case GPBDataTypeMessage:
 
1579           [toStr appendString:@"{\n"];
 
1580           NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
 
1581           AppendTextFormatForMessage(value, toStr, subIndent);
 
1582           [toStr appendFormat:@"%@  }", lineIndent];
 
1586           NSCAssert(NO, @"Can't happen");
 
1589 #pragma clang diagnostic pop
 
1590       [toStr appendString:@"\n"];
 
1592       [toStr appendString:msgEnd];
 
1595     // map is one of the GPB*Dictionary classes, type doesn't matter.
 
1596     GPBInt32Int32Dictionary *dict = map;
 
1597     [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
 
1598       [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
 
1601       // Key always is a NSString.
 
1602       if (keyDataType == GPBDataTypeString) {
 
1603         [toStr appendString:keyLine];
 
1604         AppendStringEscaped(keyObj, toStr);
 
1605         [toStr appendString:@"\n"];
 
1607         [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
 
1610       [toStr appendString:valueLine];
 
1611 #pragma clang diagnostic push
 
1612 #pragma clang diagnostic ignored "-Wswitch-enum"
 
1613       switch (valueDataType) {
 
1614         case GPBDataTypeString:
 
1615           AppendStringEscaped(valueObj, toStr);
 
1618         case GPBDataTypeBytes:
 
1619           AppendBufferAsString(valueObj, toStr);
 
1622         case GPBDataTypeMessage:
 
1623           [toStr appendString:@"{\n"];
 
1624           NSString *subIndent = [lineIndent stringByAppendingString:@"    "];
 
1625           AppendTextFormatForMessage(valueObj, toStr, subIndent);
 
1626           [toStr appendFormat:@"%@  }", lineIndent];
 
1629         case GPBDataTypeEnum: {
 
1630           int32_t enumValue = [valueObj intValue];
 
1631           NSString *valueStr = nil;
 
1632           GPBEnumDescriptor *descriptor = field.enumDescriptor;
 
1634             valueStr = [descriptor textFormatNameForValue:enumValue];
 
1637             [toStr appendString:valueStr];
 
1639             [toStr appendFormat:@"%d", enumValue];
 
1645           NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
 
1646           // Everything else is a NSString.
 
1647           [toStr appendString:valueObj];
 
1650 #pragma clang diagnostic pop
 
1651       [toStr appendString:@"\n"];
 
1653       [toStr appendString:msgEnd];
 
1658 static void AppendTextFormatForMessageField(GPBMessage *message,
 
1659                                             GPBFieldDescriptor *field,
 
1660                                             NSMutableString *toStr,
 
1661                                             NSString *lineIndent) {
 
1664   GPBFieldType fieldType = field.fieldType;
 
1665   switch (fieldType) {
 
1666     case GPBFieldTypeSingle:
 
1668       count = (GPBGetHasIvarField(message, field) ? 1 : 0);
 
1671     case GPBFieldTypeRepeated:
 
1672       // Will be NSArray or GPB*Array, type doesn't matter, they both
 
1674       arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
 
1675       count = [(NSArray *)arrayOrMap count];
 
1678     case GPBFieldTypeMap: {
 
1679       // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter,
 
1680       // they both implement count.
 
1681       arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
 
1682       count = [(NSDictionary *)arrayOrMap count];
 
1688     // Nothing to print, out of here.
 
1692   NSString *lineEnding = @"";
 
1694   // If the name can't be reversed or support for extra info was turned off,
 
1695   // this can return nil.
 
1696   NSString *fieldName = [field textFormatName];
 
1697   if ([fieldName length] == 0) {
 
1698     fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
 
1699     // If there is only one entry, put the objc name as a comment, other wise
 
1700     // add it before the repeated values.
 
1702       [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
 
1704       lineEnding = [NSString stringWithFormat:@"  # %@", field.name];
 
1708   if (fieldType == GPBFieldTypeMap) {
 
1709     AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent,
 
1710                                        fieldName, lineEnding);
 
1714   id array = arrayOrMap;
 
1715   const BOOL isRepeated = (array != nil);
 
1717   GPBDataType fieldDataType = GPBGetFieldDataType(field);
 
1718   BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
 
1719   for (NSUInteger j = 0; j < count; ++j) {
 
1721     [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
 
1722                         (isMessageField ? "" : ":")];
 
1725     switch (fieldDataType) {
 
1726 #define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...)                        \
 
1727   case GPBDataType##GPBDATATYPE: {                                            \
 
1728     CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j]   \
 
1729                           : GPBGetMessage##REAL_TYPE##Field(message, field)); \
 
1730     [toStr appendFormat:__VA_ARGS__, v];                                      \
 
1734       FIELD_CASE(Int32, int32_t, Int32, @"%d")
 
1735       FIELD_CASE(SInt32, int32_t, Int32, @"%d")
 
1736       FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
 
1737       FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
 
1738       FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
 
1739       FIELD_CASE(Int64, int64_t, Int64, @"%lld")
 
1740       FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
 
1741       FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
 
1742       FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
 
1743       FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
 
1744       FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
 
1745       FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
 
1749       case GPBDataTypeEnum: {
 
1750         int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
 
1751                                 : GPBGetMessageInt32Field(message, field));
 
1752         NSString *valueStr = nil;
 
1753         GPBEnumDescriptor *descriptor = field.enumDescriptor;
 
1755           valueStr = [descriptor textFormatNameForValue:v];
 
1758           [toStr appendString:valueStr];
 
1760           [toStr appendFormat:@"%d", v];
 
1765       case GPBDataTypeBool: {
 
1766         BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
 
1767                              : GPBGetMessageBoolField(message, field));
 
1768         [toStr appendString:(v ? @"true" : @"false")];
 
1772       case GPBDataTypeString: {
 
1773         NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
 
1774                                   : GPBGetMessageStringField(message, field));
 
1775         AppendStringEscaped(v, toStr);
 
1779       case GPBDataTypeBytes: {
 
1780         NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
 
1781                                 : GPBGetMessageBytesField(message, field));
 
1782         AppendBufferAsString(v, toStr);
 
1786       case GPBDataTypeGroup:
 
1787       case GPBDataTypeMessage: {
 
1789             (isRepeated ? [(NSArray *)array objectAtIndex:j]
 
1790                         : GPBGetObjectIvarWithField(message, field));
 
1791         [toStr appendFormat:@"{%@\n", lineEnding];
 
1792         NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
 
1793         AppendTextFormatForMessage(v, toStr, subIndent);
 
1794         [toStr appendFormat:@"%@}", lineIndent];
 
1799     }  // switch(fieldDataType)
 
1802     [toStr appendFormat:@"%@\n", lineEnding];
 
1807 static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
 
1808                                                      NSArray *activeExtensions,
 
1809                                                      GPBExtensionRange range,
 
1810                                                      NSMutableString *toStr,
 
1811                                                      NSString *lineIndent) {
 
1812   uint32_t start = range.start;
 
1813   uint32_t end = range.end;
 
1814   for (GPBExtensionDescriptor *extension in activeExtensions) {
 
1815     uint32_t fieldNumber = extension.fieldNumber;
 
1816     if (fieldNumber < start) {
 
1820     if (fieldNumber > end) {
 
1825     id rawExtValue = [message getExtension:extension];
 
1826     BOOL isRepeated = extension.isRepeated;
 
1828     NSUInteger numValues = 1;
 
1829     NSString *lineEnding = @"";
 
1831       numValues = [(NSArray *)rawExtValue count];
 
1834     NSString *singletonName = extension.singletonName;
 
1835     if (numValues == 1) {
 
1836       lineEnding = [NSString stringWithFormat:@"  # [%@]", singletonName];
 
1838       [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
 
1841     GPBDataType extDataType = extension.dataType;
 
1842     for (NSUInteger j = 0; j < numValues; ++j) {
 
1843       id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
 
1846       [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
 
1847                           (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
 
1850       switch (extDataType) {
 
1851 #define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
 
1852   case GPBDataType##GPBDATATYPE: {                       \
 
1853     CTYPE v = [(NSNumber *)curValue NUMSELECTOR];        \
 
1854     [toStr appendFormat:__VA_ARGS__, v];                 \
 
1858         FIELD_CASE(Int32, int32_t, intValue, @"%d")
 
1859         FIELD_CASE(SInt32, int32_t, intValue, @"%d")
 
1860         FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
 
1861         FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
 
1862         FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
 
1863         FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
 
1864         FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
 
1865         FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
 
1866         FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
 
1867         FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
 
1868         FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
 
1869         FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
 
1870         // TODO: Add a comment with the enum name from enum descriptors
 
1871         // (might not be real value, so leave it as a comment, ObjC compiler
 
1872         // name mangles differently).  Doesn't look like we actually generate
 
1873         // an enum descriptor reference like we do for normal fields, so this
 
1874         // will take a compiler change.
 
1875         FIELD_CASE(Enum, int32_t, intValue, @"%d")
 
1879         case GPBDataTypeBool:
 
1880           [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
 
1884         case GPBDataTypeString:
 
1885           AppendStringEscaped(curValue, toStr);
 
1888         case GPBDataTypeBytes:
 
1889           AppendBufferAsString((NSData *)curValue, toStr);
 
1892         case GPBDataTypeGroup:
 
1893         case GPBDataTypeMessage: {
 
1894           [toStr appendFormat:@"{%@\n", lineEnding];
 
1895           NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
 
1896           AppendTextFormatForMessage(curValue, toStr, subIndent);
 
1897           [toStr appendFormat:@"%@}", lineIndent];
 
1902       }  // switch(extDataType)
 
1907     [toStr appendFormat:@"%@\n", lineEnding];
 
1909   }  // for..in(activeExtensions)
 
1912 static void AppendTextFormatForMessage(GPBMessage *message,
 
1913                                        NSMutableString *toStr,
 
1914                                        NSString *lineIndent) {
 
1915   GPBDescriptor *descriptor = [message descriptor];
 
1916   NSArray *fieldsArray = descriptor->fields_;
 
1917   NSUInteger fieldCount = fieldsArray.count;
 
1918   const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
 
1919   NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
 
1920   NSArray *activeExtensions = [[message extensionsCurrentlySet]
 
1921       sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
 
1922   for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
 
1923     if (i == fieldCount) {
 
1924       AppendTextFormatForMessageExtensionRange(
 
1925           message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
 
1926     } else if (j == extensionRangesCount ||
 
1927                GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
 
1928       AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
 
1931       AppendTextFormatForMessageExtensionRange(
 
1932           message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
 
1936   NSString *unknownFieldsStr =
 
1937       GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
 
1938   if ([unknownFieldsStr length] > 0) {
 
1939     [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
 
1940     [toStr appendString:unknownFieldsStr];
 
1944 NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
 
1945   if (message == nil) return @"";
 
1946   if (lineIndent == nil) lineIndent = @"";
 
1948   NSMutableString *buildString = [NSMutableString string];
 
1949   AppendTextFormatForMessage(message, buildString, lineIndent);
 
1953 NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
 
1954                                           NSString *lineIndent) {
 
1955   if (unknownSet == nil) return @"";
 
1956   if (lineIndent == nil) lineIndent = @"";
 
1958   NSMutableString *result = [NSMutableString string];
 
1959   for (GPBUnknownField *field in [unknownSet sortedFields]) {
 
1960     int32_t fieldNumber = [field number];
 
1962 #define PRINT_LOOP(PROPNAME, CTYPE, FORMAT)                                   \
 
1964       enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) {  \
 
1965     _Pragma("unused(idx, stop)");                                             \
 
1967         appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
 
1970     PRINT_LOOP(varintList, uint64_t, %llu);
 
1971     PRINT_LOOP(fixed32List, uint32_t, 0x%X);
 
1972     PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
 
1976     // NOTE: C++ version of TextFormat tries to parse this as a message
 
1977     // and print that if it succeeds.
 
1978     for (NSData *data in field.lengthDelimitedList) {
 
1979       [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
 
1980       AppendBufferAsString(data, result);
 
1981       [result appendString:@"\n"];
 
1984     for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
 
1985       [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
 
1986       NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
 
1987       NSString *subUnknwonSetStr =
 
1988           GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
 
1989       [result appendString:subUnknwonSetStr];
 
1990       [result appendFormat:@"%@}\n", lineIndent];
 
1996 // Helpers to decode a varint. Not using GPBCodedInputStream version because
 
1997 // that needs a state object, and we don't want to create an input stream out
 
1999 GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
 
2000   int8_t result = *((int8_t *)(*data));
 
2005 static int32_t ReadRawVarint32FromData(const uint8_t **data) {
 
2006   int8_t tmp = ReadRawByteFromData(data);
 
2010   int32_t result = tmp & 0x7f;
 
2011   if ((tmp = ReadRawByteFromData(data)) >= 0) {
 
2014     result |= (tmp & 0x7f) << 7;
 
2015     if ((tmp = ReadRawByteFromData(data)) >= 0) {
 
2016       result |= tmp << 14;
 
2018       result |= (tmp & 0x7f) << 14;
 
2019       if ((tmp = ReadRawByteFromData(data)) >= 0) {
 
2020         result |= tmp << 21;
 
2022         result |= (tmp & 0x7f) << 21;
 
2023         result |= (tmp = ReadRawByteFromData(data)) << 28;
 
2025           // Discard upper 32 bits.
 
2026           for (int i = 0; i < 5; i++) {
 
2027             if (ReadRawByteFromData(data) >= 0) {
 
2031           [NSException raise:NSParseErrorException
 
2032                       format:@"Unable to read varint32"];
 
2040 NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
 
2041                                   NSString *inputStr) {
 
2043   //  varint32: num entries
 
2046   //    bytes*: decode data
 
2048   // decode data one of two forms:
 
2049   //  1: a \0 followed by the string followed by an \0
 
2050   //  2: bytecodes to transform an input into the right thing, ending with \0
 
2052   // the bytes codes are of the form:
 
2054   //  0x0 (all zeros), end.
 
2055   //  a - if set, add an underscore
 
2056   //  bb - 00 ccccc bytes as is
 
2057   //  bb - 10 ccccc upper first, as is on rest, ccccc byte total
 
2058   //  bb - 01 ccccc lower first, as is on rest, ccccc byte total
 
2059   //  bb - 11 ccccc all upper, ccccc byte total
 
2061   if (!decodeData || !inputStr) {
 
2066   const uint8_t *scan = decodeData;
 
2067   int32_t numEntries = ReadRawVarint32FromData(&scan);
 
2069   while (!foundKey && (numEntries > 0)) {
 
2071     int32_t dataKey = ReadRawVarint32FromData(&scan);
 
2072     if (dataKey == key) {
 
2075       // If it is a inlined string, it will start with \0; if it is bytecode it
 
2076       // will start with a code. So advance one (skipping the inline string
 
2077       // marker), and then loop until reaching the end marker (\0).
 
2079       while (*scan != 0) ++scan;
 
2080       // Now move past the end marker.
 
2092     // Inline string. Move over the marker, and NSString can take it as
 
2095     NSString *result = [NSString stringWithUTF8String:(const char *)scan];
 
2099   NSMutableString *result =
 
2100       [NSMutableString stringWithCapacity:[inputStr length]];
 
2102   const uint8_t kAddUnderscore  = 0b10000000;
 
2103   const uint8_t kOpMask         = 0b01100000;
 
2104   // const uint8_t kOpAsIs        = 0b00000000;
 
2105   const uint8_t kOpFirstUpper     = 0b01000000;
 
2106   const uint8_t kOpFirstLower     = 0b00100000;
 
2107   const uint8_t kOpAllUpper       = 0b01100000;
 
2108   const uint8_t kSegmentLenMask = 0b00011111;
 
2111   for (; *scan != 0; ++scan) {
 
2112     if (*scan & kAddUnderscore) {
 
2113       [result appendString:@"_"];
 
2115     int segmentLen = *scan & kSegmentLenMask;
 
2116     uint8_t decodeOp = *scan & kOpMask;
 
2118     // Do op specific handling of the first character.
 
2119     if (decodeOp == kOpFirstUpper) {
 
2120       unichar c = [inputStr characterAtIndex:i];
 
2121       [result appendFormat:@"%c", toupper((char)c)];
 
2124     } else if (decodeOp == kOpFirstLower) {
 
2125       unichar c = [inputStr characterAtIndex:i];
 
2126       [result appendFormat:@"%c", tolower((char)c)];
 
2130     // else op == kOpAsIs || op == kOpAllUpper
 
2132     // Now pull over the rest of the length for this segment.
 
2133     for (int x = 0; x < segmentLen; ++x) {
 
2134       unichar c = [inputStr characterAtIndex:(i + x)];
 
2135       if (decodeOp == kOpAllUpper) {
 
2136         [result appendFormat:@"%c", toupper((char)c)];
 
2138         [result appendFormat:@"%C", c];
 
2147 #pragma clang diagnostic pop
 
2149 BOOL GPBClassHasSel(Class aClass, SEL sel) {
 
2150   // NOTE: We have to use class_copyMethodList, all other runtime method
 
2151   // lookups actually also resolve the method implementation and this
 
2152   // is called from within those methods.
 
2155   unsigned int methodCount = 0;
 
2156   Method *methodList = class_copyMethodList(aClass, &methodCount);
 
2157   for (unsigned int i = 0; i < methodCount; ++i) {
 
2158     SEL methodSelector = method_getName(methodList[i]);
 
2159     if (methodSelector == sel) {