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