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