blob: 622db83c6affc5d8ddbc8ea39be377132aed8f4b [file] [log] [blame]
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
Thomas Van Lenten30650d82015-05-01 08:57:16 -04003//
Joshua Haberman44bd65b2023-09-08 17:43:14 -07004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Thomas Van Lenten30650d82015-05-01 08:57:16 -04007
8#import "GPBUtilities_PackagePrivate.h"
9
10#import <objc/runtime.h>
11
12#import "GPBArray_PackagePrivate.h"
13#import "GPBDescriptor_PackagePrivate.h"
14#import "GPBDictionary_PackagePrivate.h"
Thomas Van Lenten30650d82015-05-01 08:57:16 -040015#import "GPBMessage_PackagePrivate.h"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -040016#import "GPBUnknownField.h"
Thomas Van Lenten30650d82015-05-01 08:57:16 -040017#import "GPBUnknownFieldSet.h"
18
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -040019// Direct access is use for speed, to avoid even internally declaring things
20// read/write, etc. The warning is enabled in the project to ensure code calling
21// protos can turn on -Wdirect-ivar-access without issues.
22#pragma clang diagnostic push
23#pragma clang diagnostic ignored "-Wdirect-ivar-access"
24
Thomas Van Lenten189f6322022-09-19 17:21:13 -040025static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
Thomas Van Lenten30650d82015-05-01 08:57:16 -040026 NSString *lineIndent);
27
dmaclach2b3aa1c2017-11-16 05:26:46 -080028// Are two datatypes the same basic type representation (ex Int32 and SInt32).
29// Marked unused because currently only called from asserts/debug.
Thomas Van Lenten189f6322022-09-19 17:21:13 -040030static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) __attribute__((unused));
dmaclach2b3aa1c2017-11-16 05:26:46 -080031
32// Basic type representation for a type (ex: for SInt32 it is Int32).
33// Marked unused because currently only called from asserts/debug.
Thomas Van Lenten189f6322022-09-19 17:21:13 -040034static GPBDataType BaseDataType(GPBDataType type) __attribute__((unused));
dmaclach2b3aa1c2017-11-16 05:26:46 -080035
36// String name for a data type.
37// Marked unused because currently only called from asserts/debug.
Thomas Van Lenten189f6322022-09-19 17:21:13 -040038static NSString *TypeToString(GPBDataType dataType) __attribute__((unused));
dmaclach2b3aa1c2017-11-16 05:26:46 -080039
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -040040// Helper for clearing oneofs.
Thomas Van Lenten189f6322022-09-19 17:21:13 -040041static void GPBMaybeClearOneofPrivate(GPBMessage *self, GPBOneofDescriptor *oneof,
42 int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -040043
Thomas Van Lenten30650d82015-05-01 08:57:16 -040044NSData *GPBEmptyNSData(void) {
45 static dispatch_once_t onceToken;
46 static NSData *defaultNSData = nil;
47 dispatch_once(&onceToken, ^{
48 defaultNSData = [[NSData alloc] init];
49 });
50 return defaultNSData;
51}
52
Thomas Van Lentend0717662017-02-23 12:29:00 -050053void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) {
54 if (!initialMessage) {
55 return;
56 }
57
58 // Use an array as a list to process to avoid recursion.
59 NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage];
60
61 while (todo.count) {
62 GPBMessage *msg = todo.lastObject;
63 [todo removeLastObject];
64
65 // Clear unknowns.
66 msg.unknownFields = nil;
67
68 // Handle the message fields.
69 GPBDescriptor *descriptor = [[msg class] descriptor];
70 for (GPBFieldDescriptor *field in descriptor->fields_) {
71 if (!GPBFieldDataTypeIsMessage(field)) {
72 continue;
73 }
74 switch (field.fieldType) {
75 case GPBFieldTypeSingle:
76 if (GPBGetHasIvarField(msg, field)) {
77 GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
78 [todo addObject:fieldMessage];
79 }
80 break;
81
82 case GPBFieldTypeRepeated: {
83 NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
84 if (fieldMessages.count) {
85 [todo addObjectsFromArray:fieldMessages];
86 }
87 break;
88 }
89
90 case GPBFieldTypeMap: {
91 id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
92 switch (field.mapKeyDataType) {
93 case GPBDataTypeBool:
Thomas Van Lenten189f6322022-09-19 17:21:13 -040094 [(GPBBoolObjectDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -040095 enumerateKeysAndObjectsUsingBlock:^(__unused BOOL key, id _Nonnull object,
96 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -040097 [todo addObject:object];
98 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -050099 break;
100 case GPBDataTypeFixed32:
101 case GPBDataTypeUInt32:
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400102 [(GPBUInt32ObjectDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -0400103 enumerateKeysAndObjectsUsingBlock:^(__unused uint32_t key, id _Nonnull object,
104 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400105 [todo addObject:object];
106 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -0500107 break;
108 case GPBDataTypeInt32:
109 case GPBDataTypeSFixed32:
110 case GPBDataTypeSInt32:
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400111 [(GPBInt32ObjectDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -0400112 enumerateKeysAndObjectsUsingBlock:^(__unused int32_t key, id _Nonnull object,
113 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400114 [todo addObject:object];
115 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -0500116 break;
117 case GPBDataTypeFixed64:
118 case GPBDataTypeUInt64:
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400119 [(GPBUInt64ObjectDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -0400120 enumerateKeysAndObjectsUsingBlock:^(__unused uint64_t key, id _Nonnull object,
121 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400122 [todo addObject:object];
123 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -0500124 break;
125 case GPBDataTypeInt64:
126 case GPBDataTypeSFixed64:
127 case GPBDataTypeSInt64:
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400128 [(GPBInt64ObjectDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -0400129 enumerateKeysAndObjectsUsingBlock:^(__unused int64_t key, id _Nonnull object,
130 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400131 [todo addObject:object];
132 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -0500133 break;
134 case GPBDataTypeString:
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400135 [(NSDictionary *)rawFieldMap
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -0400136 enumerateKeysAndObjectsUsingBlock:^(__unused NSString *_Nonnull key,
137 GPBMessage *_Nonnull obj,
138 __unused BOOL *_Nonnull stop) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400139 [todo addObject:obj];
140 }];
Thomas Van Lentend0717662017-02-23 12:29:00 -0500141 break;
142 case GPBDataTypeFloat:
143 case GPBDataTypeDouble:
144 case GPBDataTypeEnum:
145 case GPBDataTypeBytes:
146 case GPBDataTypeGroup:
147 case GPBDataTypeMessage:
148 NSCAssert(NO, @"Aren't valid key types.");
149 }
150 break;
151 } // switch(field.mapKeyDataType)
Protobuf Team Bot7d508b42024-01-18 17:13:42 -0800152 } // switch(field.fieldType)
153 } // for(fields)
Thomas Van Lentend0717662017-02-23 12:29:00 -0500154
155 // Handle any extensions holding messages.
156 for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) {
157 if (!GPBDataTypeIsMessage(extension.dataType)) {
158 continue;
159 }
160 if (extension.isRepeated) {
161 NSArray *extMessages = [msg getExtension:extension];
162 [todo addObjectsFromArray:extMessages];
163 } else {
164 GPBMessage *extMessage = [msg getExtension:extension];
165 [todo addObject:extMessage];
166 }
167 } // for(extensionsCurrentlySet)
168
169 } // while(todo.count)
170}
171
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400172// -- About Version Checks --
173// There's actually 3 places these checks all come into play:
174// 1. When the generated source is compile into .o files, the header check
175// happens. This is checking the protoc used matches the library being used
176// when making the .o.
177// 2. Every place a generated proto header is included in a developer's code,
178// the header check comes into play again. But this time it is checking that
179// the current library headers being used still support/match the ones for
180// the generated code.
181// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is
182// called from the generated code passing in values captured when the
183// generated code's .o was made. This checks that at runtime the generated
184// code and runtime library match.
185
186void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) {
187 // NOTE: This is passing the value captured in the compiled code to check
188 // against the values captured when the runtime support was compiled. This
189 // ensures the library code isn't in a different framework/library that
190 // was generated with a non matching version.
191 if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) {
192 // Library is too old for headers.
193 [NSException raise:NSInternalInconsistencyException
194 format:@"Linked to ProtocolBuffer runtime version %d,"
Peter Newmane2cc2de2020-08-10 19:08:25 +0100195 @" but code compiled needing at least %d!",
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400196 GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
197 }
198 if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
199 // Headers are too old for library.
200 [NSException raise:NSInternalInconsistencyException
201 format:@"Proto generation source compiled against runtime"
202 @" version %d, but this version of the runtime only"
203 @" supports back to %d!",
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400204 objcRuntimeVersion, GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400205 }
206}
207
Protobuf Team Bot6e5a01b2023-01-31 13:11:17 -0800208void GPBRuntimeMatchFailure(void) {
209 [NSException raise:NSInternalInconsistencyException
210 format:@"Proto generation source appears to have been from a"
211 @" version newer that this runtime (%d).",
212 GOOGLE_PROTOBUF_OBJC_VERSION];
213}
214
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400215// This api is no longer used for version checks. 30001 is the last version
216// using this old versioning model. When that support is removed, this function
217// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h).
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400218void GPBCheckRuntimeVersionInternal(int32_t version) {
Protobuf Team Bot663fca12023-01-31 09:07:43 -0800219 GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30001,
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400220 time_to_remove_this_old_version_shim);
221 if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400222 [NSException raise:NSInternalInconsistencyException
223 format:@"Linked to ProtocolBuffer runtime version %d,"
224 @" but code compiled with version %d!",
225 GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
226 }
227}
228
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400229BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
230 GPBDescriptor *descriptor = [self descriptor];
231 GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
232 return GPBMessageHasFieldSet(self, field);
233}
234
235BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
236 if (self == nil || field == nil) return NO;
237
238 // Repeated/Map don't use the bit, they check the count.
239 if (GPBFieldIsMapOrArray(field)) {
240 // Array/map type doesn't matter, since GPB*Array/NSArray and
241 // GPB*Dictionary/NSDictionary all support -count;
242 NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
243 return (arrayOrMap.count > 0);
244 } else {
245 return GPBGetHasIvarField(self, field);
246 }
247}
248
249void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
250 // If not set, nothing to do.
251 if (!GPBGetHasIvarField(self, field)) {
252 return;
253 }
254
Thomas Van Lenten95282462020-04-07 14:43:13 -0400255 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400256 if (GPBFieldStoresObject(field)) {
257 // Object types are handled slightly differently, they need to be released.
258 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400259 id *typePtr = (id *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400260 [*typePtr release];
261 *typePtr = nil;
262 } else {
263 // POD types just need to clear the has bit as the Get* method will
264 // fetch the default when needed.
265 }
Thomas Van Lenten95282462020-04-07 14:43:13 -0400266 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400267}
268
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400269void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400270#if defined(DEBUG) && DEBUG
271 NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
272 @"OneofDescriptor %@ doesn't appear to be for %@ messages.", oneof.name, [self class]);
273#endif
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400274 GPBFieldDescriptor *firstField = oneof->fields_[0];
275 GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0);
276}
277
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400278BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400279 NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)",
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400280 [self class]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400281 if (idx < 0) {
282 NSCAssert(fieldNumber != 0, @"Invalid field number.");
283 BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
284 return hasIvar;
285 } else {
286 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
287 uint32_t byteIndex = idx / 32;
Thomas Van Lenten953adb12018-01-31 11:59:57 -0500288 uint32_t bitMask = (1U << (idx % 32));
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400289 BOOL hasIvar = (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400290 return hasIvar;
291 }
292}
293
294uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400295 NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", [self class], idx);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400296 uint32_t result = self->messageStorage_->_has_storage_[-idx];
297 return result;
298}
299
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400300void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, BOOL value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400301 if (idx < 0) {
302 NSCAssert(fieldNumber != 0, @"Invalid field number.");
303 uint32_t *has_storage = self->messageStorage_->_has_storage_;
304 has_storage[-idx] = (value ? fieldNumber : 0);
305 } else {
306 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
307 uint32_t *has_storage = self->messageStorage_->_has_storage_;
308 uint32_t byte = idx / 32;
Thomas Van Lenten953adb12018-01-31 11:59:57 -0500309 uint32_t bitMask = (1U << (idx % 32));
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400310 if (value) {
311 has_storage[byte] |= bitMask;
312 } else {
313 has_storage[byte] &= ~bitMask;
314 }
315 }
316}
317
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400318static void GPBMaybeClearOneofPrivate(GPBMessage *self, GPBOneofDescriptor *oneof,
319 int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400320 uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400321 if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
322 // Do nothing/nothing set in the oneof.
323 return;
324 }
325
326 // Like GPBClearMessageField(), free the memory if an objecttype is set,
327 // pod types don't need to do anything.
328 GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400329 NSCAssert(fieldSet, @"%@: oneof set to something (%u) not in the oneof?", [self class],
330 fieldNumberSet);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400331 if (fieldSet && GPBFieldStoresObject(fieldSet)) {
332 uint8_t *storage = (uint8_t *)self->messageStorage_;
333 id *typePtr = (id *)&storage[fieldSet->description_->offset];
334 [*typePtr release];
335 *typePtr = nil;
336 }
337
338 // Set to nothing stored in the oneof.
339 // (field number doesn't matter since setting to nothing).
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400340 GPBSetHasIvar(self, oneofHasIndex, 1, NO);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400341}
342
343#pragma mark - IVar accessors
344
Thomas Van Lenten9e069b22022-09-19 13:34:01 -0400345// clang-format off
346
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400347//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400348//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
349//% TYPE$S NAME$S GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800350//%#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400351//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
352//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
353//% field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800354//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
355//% GPBDataType##NAME),
356//% @"Attempting to get value of TYPE from field %@ "
357//% @"of %@ which is of type %@.",
358//% [self class], field.name,
359//% TypeToString(GPBGetFieldDataType(field)));
360//%#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400361//% if (GPBGetHasIvarField(self, field)) {
362//% uint8_t *storage = (uint8_t *)self->messageStorage_;
363//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
364//% return *typePtr;
365//% } else {
366//% return field.defaultValue.value##NAME;
367//% }
368//%}
369//%
370//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400371//%void GPBSetMessage##NAME##Field(GPBMessage *self,
372//% NAME$S GPBFieldDescriptor *field,
373//% NAME$S TYPE value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400374//% if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400375//%#if defined(DEBUG) && DEBUG
376//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
377//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
378//% field.name, [self class]);
379//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
380//% GPBDataType##NAME),
381//% @"Attempting to set field %@ of %@ which is of type %@ with "
382//% @"value of type TYPE.",
383//% [self class], field.name,
384//% TypeToString(GPBGetFieldDataType(field)));
385//%#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400386//% GPBSet##NAME##IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400387//%}
388//%
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400389//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
390//% NAME$S GPBFieldDescriptor *field,
391//% NAME$S TYPE value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400392//% GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400393//% GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400394//% if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400395//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400396//% }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800397//%#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400398//% NSCAssert(self->messageStorage_ != NULL,
399//% @"%@: All messages should have storage (from init)",
400//% [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800401//%#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400402//%#if defined(__clang_analyzer__)
403//% if (self->messageStorage_ == NULL) return;
404//%#endif
405//% uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400406//% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400407//% *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400408//% // If the value is zero, then we only count the field as "set" if the field
409//% // shouldn't auto clear on zero.
410//% BOOL hasValue = ((value != (TYPE)0)
411//% || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400412//% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400413//% GPBBecomeVisibleToAutocreator(self);
414//%}
415//%
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400416//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400417//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400418//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
419//% TYPE$S NAME$S GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800420//%#if defined(DEBUG) && DEBUG
421//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
422//% GPBDataType##NAME),
423//% @"Attempting to get value of TYPE from field %@ "
424//% @"of %@ which is of type %@.",
425//% [self class], field.name,
426//% TypeToString(GPBGetFieldDataType(field)));
427//%#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400428//% return (TYPE *)GPBGetObjectIvarWithField(self, field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400429//%}
430//%
431//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400432//%void GPBSetMessage##NAME##Field(GPBMessage *self,
433//% NAME$S GPBFieldDescriptor *field,
434//% NAME$S TYPE *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800435//%#if defined(DEBUG) && DEBUG
436//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
437//% GPBDataType##NAME),
438//% @"Attempting to set field %@ of %@ which is of type %@ with "
439//% @"value of type TYPE.",
440//% [self class], field.name,
441//% TypeToString(GPBGetFieldDataType(field)));
442//%#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400443//% GPBSetObjectIvarWithField(self, field, (id)value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400444//%}
445//%
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400446//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE)
447//%// Only exists for public api, no core code should use this.
448//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
449//% TYPE$S NAME$S GPBFieldDescriptor *field) {
450//%#if defined(DEBUG) && DEBUG
451//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
452//% GPBDataType##NAME),
453//% @"Attempting to get value of TYPE from field %@ "
454//% @"of %@ which is of type %@.",
455//% [self class], field.name,
456//% TypeToString(GPBGetFieldDataType(field)));
457//%#endif
458//% return (TYPE *)GPBGetObjectIvarWithField(self, field);
459//%}
460//%
461//%// Only exists for public api, no core code should use this.
462//%void GPBSetMessage##NAME##Field(GPBMessage *self,
463//% NAME$S GPBFieldDescriptor *field,
464//% NAME$S TYPE *value) {
465//%#if defined(DEBUG) && DEBUG
466//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
467//% GPBDataType##NAME),
468//% @"Attempting to set field %@ of %@ which is of type %@ with "
469//% @"value of type TYPE.",
470//% [self class], field.name,
471//% TypeToString(GPBGetFieldDataType(field)));
472//%#endif
473//% GPBSetCopyObjectIvarWithField(self, field, (id)value);
474//%}
475//%
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400476
Thomas Van Lenten9e069b22022-09-19 13:34:01 -0400477// clang-format on
478
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400479// Object types are handled slightly differently, they need to be released
480// and retained.
481
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400482void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400483 if (GPBGetHasIvarField(self, field)) {
484 return;
485 }
486 uint8_t *storage = (uint8_t *)self->messageStorage_;
487 id *typePtr = (id *)&storage[field->description_->offset];
488 GPBMessage *oldValue = *typePtr;
489 *typePtr = NULL;
490 GPBClearMessageAutocreator(oldValue);
491 [oldValue release];
492}
493
Brian Wignalla104dff2020-01-08 13:18:20 -0500494// This exists only for bridging some aliased types, nothing else should use it.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400495static void GPBSetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400496 if (self == nil || field == nil) return;
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400497 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400498}
499
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400500static void GPBSetCopyObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value);
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400501
502// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400503// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400504// is marked as consuming the value. Note: For some reason this doesn't happen
505// with the -retain in GPBSetObjectIvarWithField.
506#if !defined(__clang_analyzer__)
Brian Wignalla104dff2020-01-08 13:18:20 -0500507// This exists only for bridging some aliased types, nothing else should use it.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400508static void GPBSetCopyObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) {
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400509 if (self == nil || field == nil) return;
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400510 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]);
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400511}
512#endif // !defined(__clang_analyzer__)
513
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400514void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, id value) {
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400515 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400516}
517
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400518void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field,
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400519 id value) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400520 NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)",
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400521 [self class]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400522#if defined(__clang_analyzer__)
523 if (self->messageStorage_ == NULL) return;
524#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400525 GPBDataType fieldType = GPBGetFieldDataType(field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400526 BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400527 BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800528#if defined(DEBUG) && DEBUG
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400529 if (value == nil && !isMapOrArray && !fieldIsMessage && field.hasDefaultValue) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400530 // Setting a message to nil is an obvious way to "clear" the value
531 // as there is no way to set a non-empty default value for messages.
532 //
533 // For Strings and Bytes that have default values set it is not clear what
534 // should be done when their value is set to nil. Is the intention just to
535 // clear the set value and reset to default, or is the intention to set the
536 // value to the empty string/data? Arguments can be made for both cases.
537 // 'nil' has been abused as a replacement for an empty string/data in ObjC.
538 // We decided to be consistent with all "object" types and clear the has
539 // field, and fall back on the default value. The warning below will only
540 // appear in debug, but the could should be changed so the intention is
541 // clear.
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400542 NSString *propName = field.name;
543 NSString *className = self.descriptor.name;
Dave MacLachlanb375d012024-04-09 09:00:58 -0700544 NSString *firstLetterCapitalizedName = [[[className substringToIndex:1] uppercaseString]
545 stringByAppendingString:[className substringFromIndex:1]];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400546 NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
547 @"default values. Please use '%@.%@ = %@' if you want to set it to "
Dave MacLachlanb375d012024-04-09 09:00:58 -0700548 @"empty, or call '%@.has%@ = NO' to reset it to it's default value of "
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400549 @"'%@'. Defaulting to resetting default value.",
550 className, propName, className, propName,
Dave MacLachlanb375d012024-04-09 09:00:58 -0700551 (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", className,
552 firstLetterCapitalizedName, field.defaultValue.valueString);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400553 // Note: valueString, depending on the type, it could easily be
554 // valueData/valueMessage.
555 }
556#endif // DEBUG
Thomas Van Lenten95282462020-04-07 14:43:13 -0400557 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400558 if (!isMapOrArray) {
559 // Non repeated/map can be in an oneof, clear any existing value from the
560 // oneof.
561 GPBOneofDescriptor *oneof = field->containingOneof_;
562 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400563 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400564 }
565 // Clear "has" if they are being set to nil.
566 BOOL setHasValue = (value != nil);
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400567 // If the field should clear on a "zero" value, then check if the string/data
568 // was zero length, and clear instead.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400569 if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) && ([value length] == 0)) {
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400570 setHasValue = NO;
571 // The value passed in was retained, it must be released since we
572 // aren't saving anything in the field.
573 [value release];
574 value = nil;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400575 }
Thomas Van Lenten95282462020-04-07 14:43:13 -0400576 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400577 }
578 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400579 id *typePtr = (id *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400580
581 id oldValue = *typePtr;
582
583 *typePtr = value;
584
585 if (oldValue) {
586 if (isMapOrArray) {
587 if (field.fieldType == GPBFieldTypeRepeated) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400588 // If the old array was autocreated by us, then clear it.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400589 if (GPBDataTypeIsObject(fieldType)) {
Thomas Van Lenten988ffe02017-01-04 15:03:42 -0500590 if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) {
591 GPBAutocreatedArray *autoArray = oldValue;
592 if (autoArray->_autocreator == self) {
593 autoArray->_autocreator = nil;
594 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400595 }
596 } else {
597 // Type doesn't matter, it is a GPB*Array.
598 GPBInt32Array *gpbArray = oldValue;
599 if (gpbArray->_autocreator == self) {
600 gpbArray->_autocreator = nil;
601 }
602 }
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400603 } else { // GPBFieldTypeMap
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400604 // If the old map was autocreated by us, then clear it.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400605 if ((field.mapKeyDataType == GPBDataTypeString) && GPBDataTypeIsObject(fieldType)) {
Thomas Van Lenten988ffe02017-01-04 15:03:42 -0500606 if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
607 GPBAutocreatedDictionary *autoDict = oldValue;
608 if (autoDict->_autocreator == self) {
609 autoDict->_autocreator = nil;
610 }
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400611 }
612 } else {
613 // Type doesn't matter, it is a GPB*Dictionary.
614 GPBInt32Int32Dictionary *gpbDict = oldValue;
615 if (gpbDict->_autocreator == self) {
616 gpbDict->_autocreator = nil;
617 }
618 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400619 }
620 } else if (fieldIsMessage) {
621 // If the old message value was autocreated by us, then clear it.
622 GPBMessage *oldMessageValue = oldValue;
623 if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
624 GPBClearMessageAutocreator(oldMessageValue);
625 }
626 }
627 [oldValue release];
628 }
629
630 GPBBecomeVisibleToAutocreator(self);
631}
632
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400633id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, GPBFieldDescriptor *field) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400634 if (self->messageStorage_ == nil) {
635 return nil;
636 }
637 uint8_t *storage = (uint8_t *)self->messageStorage_;
638 id *typePtr = (id *)&storage[field->description_->offset];
639 return *typePtr;
640}
641
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400642// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400643int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400644#if defined(DEBUG) && DEBUG
645 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
646 @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
647 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
648 @"Attempting to get value of type Enum from field %@ "
649 @"of %@ which is of type %@.",
650 [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
651#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400652
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400653 int32_t result = GPBGetMessageInt32Field(self, field);
654 // If this is presevering unknown enums, make sure the value is valid before
655 // returning it.
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400656
Protobuf Team Bot7bb699b2022-11-15 08:59:25 -0800657 if (!GPBFieldIsClosedEnum(field) && ![field isValidEnumValue:result]) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400658 result = kGPBUnrecognizedEnumeratorValue;
659 }
660 return result;
661}
662
663// Only exists for public api, no core code should use this.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400664void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) {
665#if defined(DEBUG) && DEBUG
666 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
667 @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
668 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
669 @"Attempting to set field %@ of %@ which is of type %@ with "
670 @"value of type Enum.",
671 [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
672#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400673 GPBSetEnumIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400674}
675
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400676void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400677 // Don't allow in unknown values. Proto3 can use the Raw method.
678 if (![field isValidEnumValue:value]) {
679 [NSException raise:NSInvalidArgumentException
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400680 format:@"%@.%@: Attempt to set an unknown enum value (%d)", [self class],
681 field.name, value];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400682 }
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400683 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400684}
685
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400686// Only exists for public api, no core code should use this.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400687int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400688 int32_t result = GPBGetMessageInt32Field(self, field);
689 return result;
690}
691
692// Only exists for public api, no core code should use this.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400693void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) {
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400694 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400695}
696
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400697BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800698#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400699 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400700 @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800701 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
702 @"Attempting to get value of type bool from field %@ "
703 @"of %@ which is of type %@.",
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400704 [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
dmaclach2b3aa1c2017-11-16 05:26:46 -0800705#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400706 if (GPBGetHasIvarField(self, field)) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400707 // Bools are stored in the has bits to avoid needing explicit space in the
708 // storage structure.
709 // (the field number passed to the HasIvar helper doesn't really matter
710 // since the offset is never negative)
711 GPBMessageFieldDescription *fieldDesc = field->description_;
712 return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400713 } else {
714 return field.defaultValue.valueBool;
715 }
716}
717
718// Only exists for public api, no core code should use this.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400719void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400720 if (self == nil || field == nil) return;
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400721#if defined(DEBUG) && DEBUG
722 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
723 @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
724 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
725 @"Attempting to set field %@ of %@ which is of type %@ with "
726 @"value of type bool.",
727 [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
728#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400729 GPBSetBoolIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400730}
731
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400732void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400733 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400734 GPBOneofDescriptor *oneof = field->containingOneof_;
735 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400736 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400737 }
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400738
739 // Bools are stored in the has bits to avoid needing explicit space in the
740 // storage structure.
741 // (the field number passed to the HasIvar helper doesn't really matter since
742 // the offset is never negative)
743 GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
744
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400745 // If the value is zero, then we only count the field as "set" if the field
746 // shouldn't auto clear on zero.
Thomas Van Lenten189f6322022-09-19 17:21:13 -0400747 BOOL hasValue = ((value != (BOOL)0) || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400748 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400749 GPBBecomeVisibleToAutocreator(self);
750}
751
Thomas Van Lenten9e069b22022-09-19 13:34:01 -0400752// clang-format off
753
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400754//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
755// This block of code is generated, do not edit it directly.
756
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400757int32_t GPBGetMessageInt32Field(GPBMessage *self,
758 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800759#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400760 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
761 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
762 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800763 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
764 GPBDataTypeInt32),
765 @"Attempting to get value of int32_t from field %@ "
766 @"of %@ which is of type %@.",
767 [self class], field.name,
768 TypeToString(GPBGetFieldDataType(field)));
769#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400770 if (GPBGetHasIvarField(self, field)) {
771 uint8_t *storage = (uint8_t *)self->messageStorage_;
772 int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
773 return *typePtr;
774 } else {
775 return field.defaultValue.valueInt32;
776 }
777}
778
779// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400780void GPBSetMessageInt32Field(GPBMessage *self,
781 GPBFieldDescriptor *field,
782 int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400783 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400784#if defined(DEBUG) && DEBUG
785 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
786 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
787 field.name, [self class]);
788 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
789 GPBDataTypeInt32),
790 @"Attempting to set field %@ of %@ which is of type %@ with "
791 @"value of type int32_t.",
792 [self class], field.name,
793 TypeToString(GPBGetFieldDataType(field)));
794#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400795 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400796}
797
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400798void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
799 GPBFieldDescriptor *field,
800 int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400801 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400802 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400803 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400804 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400805 }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800806#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400807 NSCAssert(self->messageStorage_ != NULL,
808 @"%@: All messages should have storage (from init)",
809 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800810#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400811#if defined(__clang_analyzer__)
812 if (self->messageStorage_ == NULL) return;
813#endif
814 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400815 int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400816 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400817 // If the value is zero, then we only count the field as "set" if the field
818 // shouldn't auto clear on zero.
819 BOOL hasValue = ((value != (int32_t)0)
820 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400821 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400822 GPBBecomeVisibleToAutocreator(self);
823}
824
825//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
826// This block of code is generated, do not edit it directly.
827
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400828uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
829 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800830#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400831 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
832 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
833 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800834 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
835 GPBDataTypeUInt32),
836 @"Attempting to get value of uint32_t from field %@ "
837 @"of %@ which is of type %@.",
838 [self class], field.name,
839 TypeToString(GPBGetFieldDataType(field)));
840#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400841 if (GPBGetHasIvarField(self, field)) {
842 uint8_t *storage = (uint8_t *)self->messageStorage_;
843 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
844 return *typePtr;
845 } else {
846 return field.defaultValue.valueUInt32;
847 }
848}
849
850// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400851void GPBSetMessageUInt32Field(GPBMessage *self,
852 GPBFieldDescriptor *field,
853 uint32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400854 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400855#if defined(DEBUG) && DEBUG
856 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
857 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
858 field.name, [self class]);
859 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
860 GPBDataTypeUInt32),
861 @"Attempting to set field %@ of %@ which is of type %@ with "
862 @"value of type uint32_t.",
863 [self class], field.name,
864 TypeToString(GPBGetFieldDataType(field)));
865#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400866 GPBSetUInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400867}
868
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400869void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
870 GPBFieldDescriptor *field,
871 uint32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400872 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400873 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400874 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400875 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400876 }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800877#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400878 NSCAssert(self->messageStorage_ != NULL,
879 @"%@: All messages should have storage (from init)",
880 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800881#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400882#if defined(__clang_analyzer__)
883 if (self->messageStorage_ == NULL) return;
884#endif
885 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400886 uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400887 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400888 // If the value is zero, then we only count the field as "set" if the field
889 // shouldn't auto clear on zero.
890 BOOL hasValue = ((value != (uint32_t)0)
891 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400892 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400893 GPBBecomeVisibleToAutocreator(self);
894}
895
896//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
897// This block of code is generated, do not edit it directly.
898
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400899int64_t GPBGetMessageInt64Field(GPBMessage *self,
900 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800901#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400902 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
903 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
904 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800905 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
906 GPBDataTypeInt64),
907 @"Attempting to get value of int64_t from field %@ "
908 @"of %@ which is of type %@.",
909 [self class], field.name,
910 TypeToString(GPBGetFieldDataType(field)));
911#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400912 if (GPBGetHasIvarField(self, field)) {
913 uint8_t *storage = (uint8_t *)self->messageStorage_;
914 int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
915 return *typePtr;
916 } else {
917 return field.defaultValue.valueInt64;
918 }
919}
920
921// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400922void GPBSetMessageInt64Field(GPBMessage *self,
923 GPBFieldDescriptor *field,
924 int64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400925 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400926#if defined(DEBUG) && DEBUG
927 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
928 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
929 field.name, [self class]);
930 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
931 GPBDataTypeInt64),
932 @"Attempting to set field %@ of %@ which is of type %@ with "
933 @"value of type int64_t.",
934 [self class], field.name,
935 TypeToString(GPBGetFieldDataType(field)));
936#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400937 GPBSetInt64IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400938}
939
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400940void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
941 GPBFieldDescriptor *field,
942 int64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400943 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400944 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400945 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400946 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400947 }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800948#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400949 NSCAssert(self->messageStorage_ != NULL,
950 @"%@: All messages should have storage (from init)",
951 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800952#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400953#if defined(__clang_analyzer__)
954 if (self->messageStorage_ == NULL) return;
955#endif
956 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400957 int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400958 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400959 // If the value is zero, then we only count the field as "set" if the field
960 // shouldn't auto clear on zero.
961 BOOL hasValue = ((value != (int64_t)0)
962 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400963 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400964 GPBBecomeVisibleToAutocreator(self);
965}
966
967//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
968// This block of code is generated, do not edit it directly.
969
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400970uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
971 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800972#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400973 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
974 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
975 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800976 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
977 GPBDataTypeUInt64),
978 @"Attempting to get value of uint64_t from field %@ "
979 @"of %@ which is of type %@.",
980 [self class], field.name,
981 TypeToString(GPBGetFieldDataType(field)));
982#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400983 if (GPBGetHasIvarField(self, field)) {
984 uint8_t *storage = (uint8_t *)self->messageStorage_;
985 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
986 return *typePtr;
987 } else {
988 return field.defaultValue.valueUInt64;
989 }
990}
991
992// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400993void GPBSetMessageUInt64Field(GPBMessage *self,
994 GPBFieldDescriptor *field,
995 uint64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400996 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400997#if defined(DEBUG) && DEBUG
998 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
999 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1000 field.name, [self class]);
1001 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1002 GPBDataTypeUInt64),
1003 @"Attempting to set field %@ of %@ which is of type %@ with "
1004 @"value of type uint64_t.",
1005 [self class], field.name,
1006 TypeToString(GPBGetFieldDataType(field)));
1007#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001008 GPBSetUInt64IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001009}
1010
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001011void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
1012 GPBFieldDescriptor *field,
1013 uint64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001014 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001015 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001016 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001017 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001018 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001019#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001020 NSCAssert(self->messageStorage_ != NULL,
1021 @"%@: All messages should have storage (from init)",
1022 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001023#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001024#if defined(__clang_analyzer__)
1025 if (self->messageStorage_ == NULL) return;
1026#endif
1027 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001028 uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001029 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001030 // If the value is zero, then we only count the field as "set" if the field
1031 // shouldn't auto clear on zero.
1032 BOOL hasValue = ((value != (uint64_t)0)
1033 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001034 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001035 GPBBecomeVisibleToAutocreator(self);
1036}
1037
1038//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
1039// This block of code is generated, do not edit it directly.
1040
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001041float GPBGetMessageFloatField(GPBMessage *self,
1042 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001043#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001044 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1045 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1046 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001047 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1048 GPBDataTypeFloat),
1049 @"Attempting to get value of float from field %@ "
1050 @"of %@ which is of type %@.",
1051 [self class], field.name,
1052 TypeToString(GPBGetFieldDataType(field)));
1053#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001054 if (GPBGetHasIvarField(self, field)) {
1055 uint8_t *storage = (uint8_t *)self->messageStorage_;
1056 float *typePtr = (float *)&storage[field->description_->offset];
1057 return *typePtr;
1058 } else {
1059 return field.defaultValue.valueFloat;
1060 }
1061}
1062
1063// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001064void GPBSetMessageFloatField(GPBMessage *self,
1065 GPBFieldDescriptor *field,
1066 float value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001067 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001068#if defined(DEBUG) && DEBUG
1069 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1070 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1071 field.name, [self class]);
1072 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1073 GPBDataTypeFloat),
1074 @"Attempting to set field %@ of %@ which is of type %@ with "
1075 @"value of type float.",
1076 [self class], field.name,
1077 TypeToString(GPBGetFieldDataType(field)));
1078#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001079 GPBSetFloatIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001080}
1081
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001082void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
1083 GPBFieldDescriptor *field,
1084 float value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001085 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001086 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001087 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001088 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001089 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001090#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001091 NSCAssert(self->messageStorage_ != NULL,
1092 @"%@: All messages should have storage (from init)",
1093 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001094#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001095#if defined(__clang_analyzer__)
1096 if (self->messageStorage_ == NULL) return;
1097#endif
1098 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001099 float *typePtr = (float *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001100 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001101 // If the value is zero, then we only count the field as "set" if the field
1102 // shouldn't auto clear on zero.
1103 BOOL hasValue = ((value != (float)0)
1104 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001105 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001106 GPBBecomeVisibleToAutocreator(self);
1107}
1108
1109//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
1110// This block of code is generated, do not edit it directly.
1111
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001112double GPBGetMessageDoubleField(GPBMessage *self,
1113 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001114#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001115 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1116 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1117 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001118 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1119 GPBDataTypeDouble),
1120 @"Attempting to get value of double from field %@ "
1121 @"of %@ which is of type %@.",
1122 [self class], field.name,
1123 TypeToString(GPBGetFieldDataType(field)));
1124#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001125 if (GPBGetHasIvarField(self, field)) {
1126 uint8_t *storage = (uint8_t *)self->messageStorage_;
1127 double *typePtr = (double *)&storage[field->description_->offset];
1128 return *typePtr;
1129 } else {
1130 return field.defaultValue.valueDouble;
1131 }
1132}
1133
1134// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001135void GPBSetMessageDoubleField(GPBMessage *self,
1136 GPBFieldDescriptor *field,
1137 double value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001138 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001139#if defined(DEBUG) && DEBUG
1140 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1141 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1142 field.name, [self class]);
1143 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1144 GPBDataTypeDouble),
1145 @"Attempting to set field %@ of %@ which is of type %@ with "
1146 @"value of type double.",
1147 [self class], field.name,
1148 TypeToString(GPBGetFieldDataType(field)));
1149#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001150 GPBSetDoubleIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001151}
1152
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001153void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
1154 GPBFieldDescriptor *field,
1155 double value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001156 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001157 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001158 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001159 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001160 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001161#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001162 NSCAssert(self->messageStorage_ != NULL,
1163 @"%@: All messages should have storage (from init)",
1164 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001165#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001166#if defined(__clang_analyzer__)
1167 if (self->messageStorage_ == NULL) return;
1168#endif
1169 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001170 double *typePtr = (double *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001171 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001172 // If the value is zero, then we only count the field as "set" if the field
1173 // shouldn't auto clear on zero.
1174 BOOL hasValue = ((value != (double)0)
1175 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001176 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001177 GPBBecomeVisibleToAutocreator(self);
1178}
1179
Thomas Van Lenten79a23c42016-03-17 10:04:21 -04001180//%PDDM-EXPAND-END (6 expansions)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001181
1182// Aliases are function calls that are virtually the same.
1183
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001184//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001185// This block of code is generated, do not edit it directly.
1186
1187// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001188NSString *GPBGetMessageStringField(GPBMessage *self,
1189 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001190#if defined(DEBUG) && DEBUG
1191 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1192 GPBDataTypeString),
1193 @"Attempting to get value of NSString from field %@ "
1194 @"of %@ which is of type %@.",
1195 [self class], field.name,
1196 TypeToString(GPBGetFieldDataType(field)));
1197#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001198 return (NSString *)GPBGetObjectIvarWithField(self, field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001199}
1200
1201// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001202void GPBSetMessageStringField(GPBMessage *self,
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001203 GPBFieldDescriptor *field,
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001204 NSString *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001205#if defined(DEBUG) && DEBUG
1206 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1207 GPBDataTypeString),
1208 @"Attempting to set field %@ of %@ which is of type %@ with "
1209 @"value of type NSString.",
1210 [self class], field.name,
1211 TypeToString(GPBGetFieldDataType(field)));
1212#endif
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001213 GPBSetCopyObjectIvarWithField(self, field, (id)value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001214}
1215
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001216//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData)
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001217// This block of code is generated, do not edit it directly.
1218
1219// Only exists for public api, no core code should use this.
1220NSData *GPBGetMessageBytesField(GPBMessage *self,
1221 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001222#if defined(DEBUG) && DEBUG
1223 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1224 GPBDataTypeBytes),
1225 @"Attempting to get value of NSData from field %@ "
1226 @"of %@ which is of type %@.",
1227 [self class], field.name,
1228 TypeToString(GPBGetFieldDataType(field)));
1229#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001230 return (NSData *)GPBGetObjectIvarWithField(self, field);
1231}
1232
1233// Only exists for public api, no core code should use this.
1234void GPBSetMessageBytesField(GPBMessage *self,
1235 GPBFieldDescriptor *field,
1236 NSData *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001237#if defined(DEBUG) && DEBUG
1238 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1239 GPBDataTypeBytes),
1240 @"Attempting to set field %@ of %@ which is of type %@ with "
1241 @"value of type NSData.",
1242 [self class], field.name,
1243 TypeToString(GPBGetFieldDataType(field)));
1244#endif
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001245 GPBSetCopyObjectIvarWithField(self, field, (id)value);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001246}
1247
1248//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
1249// This block of code is generated, do not edit it directly.
1250
1251// Only exists for public api, no core code should use this.
1252GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
1253 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001254#if defined(DEBUG) && DEBUG
1255 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1256 GPBDataTypeMessage),
1257 @"Attempting to get value of GPBMessage from field %@ "
1258 @"of %@ which is of type %@.",
1259 [self class], field.name,
1260 TypeToString(GPBGetFieldDataType(field)));
1261#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001262 return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
1263}
1264
1265// Only exists for public api, no core code should use this.
1266void GPBSetMessageMessageField(GPBMessage *self,
1267 GPBFieldDescriptor *field,
1268 GPBMessage *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001269#if defined(DEBUG) && DEBUG
1270 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1271 GPBDataTypeMessage),
1272 @"Attempting to set field %@ of %@ which is of type %@ with "
1273 @"value of type GPBMessage.",
1274 [self class], field.name,
1275 TypeToString(GPBGetFieldDataType(field)));
1276#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001277 GPBSetObjectIvarWithField(self, field, (id)value);
1278}
1279
1280//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
1281// This block of code is generated, do not edit it directly.
1282
1283// Only exists for public api, no core code should use this.
1284GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
1285 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001286#if defined(DEBUG) && DEBUG
1287 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1288 GPBDataTypeGroup),
1289 @"Attempting to get value of GPBMessage from field %@ "
1290 @"of %@ which is of type %@.",
1291 [self class], field.name,
1292 TypeToString(GPBGetFieldDataType(field)));
1293#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001294 return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
1295}
1296
1297// Only exists for public api, no core code should use this.
1298void GPBSetMessageGroupField(GPBMessage *self,
1299 GPBFieldDescriptor *field,
1300 GPBMessage *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001301#if defined(DEBUG) && DEBUG
1302 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1303 GPBDataTypeGroup),
1304 @"Attempting to set field %@ of %@ which is of type %@ with "
1305 @"value of type GPBMessage.",
1306 [self class], field.name,
1307 TypeToString(GPBGetFieldDataType(field)));
1308#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001309 GPBSetObjectIvarWithField(self, field, (id)value);
1310}
1311
1312//%PDDM-EXPAND-END (4 expansions)
1313
Thomas Van Lenten9e069b22022-09-19 13:34:01 -04001314// clang-format on
1315
Thomas Van Lentenfc4c6172016-06-27 20:45:16 -04001316// GPBGetMessageRepeatedField is defined in GPBMessage.m
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001317
1318// Only exists for public api, no core code should use this.
1319void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001320#if defined(DEBUG) && DEBUG
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001321 if (field.fieldType != GPBFieldTypeRepeated) {
1322 [NSException raise:NSInvalidArgumentException
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001323 format:@"%@.%@ is not a repeated field.", [self class], field.name];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001324 }
1325 Class expectedClass = Nil;
1326 switch (GPBGetFieldDataType(field)) {
1327 case GPBDataTypeBool:
1328 expectedClass = [GPBBoolArray class];
1329 break;
1330 case GPBDataTypeSFixed32:
1331 case GPBDataTypeInt32:
1332 case GPBDataTypeSInt32:
1333 expectedClass = [GPBInt32Array class];
1334 break;
1335 case GPBDataTypeFixed32:
1336 case GPBDataTypeUInt32:
1337 expectedClass = [GPBUInt32Array class];
1338 break;
1339 case GPBDataTypeSFixed64:
1340 case GPBDataTypeInt64:
1341 case GPBDataTypeSInt64:
1342 expectedClass = [GPBInt64Array class];
1343 break;
1344 case GPBDataTypeFixed64:
1345 case GPBDataTypeUInt64:
1346 expectedClass = [GPBUInt64Array class];
1347 break;
1348 case GPBDataTypeFloat:
1349 expectedClass = [GPBFloatArray class];
1350 break;
1351 case GPBDataTypeDouble:
1352 expectedClass = [GPBDoubleArray class];
1353 break;
1354 case GPBDataTypeBytes:
1355 case GPBDataTypeString:
1356 case GPBDataTypeMessage:
1357 case GPBDataTypeGroup:
Jon Walle72805e2016-05-26 12:23:41 -04001358 expectedClass = [NSMutableArray class];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001359 break;
1360 case GPBDataTypeEnum:
Jon Walle72805e2016-05-26 12:23:41 -04001361 expectedClass = [GPBEnumArray class];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001362 break;
1363 }
1364 if (array && ![array isKindOfClass:expectedClass]) {
1365 [NSException raise:NSInvalidArgumentException
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001366 format:@"%@.%@: Expected %@ object, got %@.", [self class], field.name,
1367 expectedClass, [array class]];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001368 }
1369#endif
1370 GPBSetObjectIvarWithField(self, field, array);
1371}
1372
dmaclach2b3aa1c2017-11-16 05:26:46 -08001373static GPBDataType BaseDataType(GPBDataType type) {
1374 switch (type) {
1375 case GPBDataTypeSFixed32:
1376 case GPBDataTypeInt32:
1377 case GPBDataTypeSInt32:
1378 case GPBDataTypeEnum:
1379 return GPBDataTypeInt32;
1380 case GPBDataTypeFixed32:
1381 case GPBDataTypeUInt32:
1382 return GPBDataTypeUInt32;
1383 case GPBDataTypeSFixed64:
1384 case GPBDataTypeInt64:
1385 case GPBDataTypeSInt64:
1386 return GPBDataTypeInt64;
1387 case GPBDataTypeFixed64:
1388 case GPBDataTypeUInt64:
1389 return GPBDataTypeUInt64;
1390 case GPBDataTypeMessage:
1391 case GPBDataTypeGroup:
1392 return GPBDataTypeMessage;
1393 case GPBDataTypeBool:
1394 case GPBDataTypeFloat:
1395 case GPBDataTypeDouble:
1396 case GPBDataTypeBytes:
1397 case GPBDataTypeString:
1398 return type;
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001399 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001400}
1401
1402static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) {
1403 return BaseDataType(type1) == BaseDataType(type2);
1404}
1405
1406static NSString *TypeToString(GPBDataType dataType) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001407 switch (dataType) {
1408 case GPBDataTypeBool:
1409 return @"Bool";
1410 case GPBDataTypeSFixed32:
1411 case GPBDataTypeInt32:
1412 case GPBDataTypeSInt32:
1413 return @"Int32";
1414 case GPBDataTypeFixed32:
1415 case GPBDataTypeUInt32:
1416 return @"UInt32";
1417 case GPBDataTypeSFixed64:
1418 case GPBDataTypeInt64:
1419 case GPBDataTypeSInt64:
1420 return @"Int64";
1421 case GPBDataTypeFixed64:
1422 case GPBDataTypeUInt64:
1423 return @"UInt64";
1424 case GPBDataTypeFloat:
1425 return @"Float";
1426 case GPBDataTypeDouble:
1427 return @"Double";
1428 case GPBDataTypeBytes:
1429 case GPBDataTypeString:
1430 case GPBDataTypeMessage:
1431 case GPBDataTypeGroup:
1432 return @"Object";
1433 case GPBDataTypeEnum:
dmaclach2b3aa1c2017-11-16 05:26:46 -08001434 return @"Enum";
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001435 }
1436}
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001437
Thomas Van Lentenfc4c6172016-06-27 20:45:16 -04001438// GPBGetMessageMapField is defined in GPBMessage.m
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001439
1440// Only exists for public api, no core code should use this.
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001441void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary) {
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001442#if defined(DEBUG) && DEBUG
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001443 if (field.fieldType != GPBFieldTypeMap) {
1444 [NSException raise:NSInvalidArgumentException
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001445 format:@"%@.%@ is not a map<> field.", [self class], field.name];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001446 }
1447 if (dictionary) {
1448 GPBDataType keyDataType = field.mapKeyDataType;
1449 GPBDataType valueDataType = GPBGetFieldDataType(field);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001450 NSString *keyStr = TypeToString(keyDataType);
1451 NSString *valueStr = TypeToString(valueDataType);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001452 if (keyDataType == GPBDataTypeString) {
1453 keyStr = @"String";
1454 }
1455 Class expectedClass = Nil;
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001456 if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001457 expectedClass = [NSMutableDictionary class];
1458 } else {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001459 NSString *className = [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001460 expectedClass = NSClassFromString(className);
1461 NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
1462 }
1463 if (![dictionary isKindOfClass:expectedClass]) {
1464 [NSException raise:NSInvalidArgumentException
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001465 format:@"%@.%@: Expected %@ object, got %@.", [self class], field.name,
1466 expectedClass, [dictionary class]];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001467 }
1468 }
1469#endif
1470 GPBSetObjectIvarWithField(self, field, dictionary);
1471}
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001472
1473#pragma mark - Misc Dynamic Runtime Utils
1474
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001475const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001476 Protocol *protocol = objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
Dave MacLachlan37a66722017-11-14 15:16:04 -08001477 NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol");
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001478 struct objc_method_description description =
1479 protocol_getMethodDescription(protocol, selector, NO, instanceSel);
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001480 NSCAssert(description.name != Nil && description.types != nil, @"Missing method for selector %@",
1481 NSStringFromSelector(selector));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001482 return description.types;
1483}
1484
1485#pragma mark - Text Format Support
1486
1487static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
1488 [destStr appendString:@"\""];
1489 NSUInteger len = [toPrint length];
1490 for (NSUInteger i = 0; i < len; ++i) {
1491 unichar aChar = [toPrint characterAtIndex:i];
1492 switch (aChar) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001493 case '\n':
1494 [destStr appendString:@"\\n"];
1495 break;
1496 case '\r':
1497 [destStr appendString:@"\\r"];
1498 break;
1499 case '\t':
1500 [destStr appendString:@"\\t"];
1501 break;
1502 case '\"':
1503 [destStr appendString:@"\\\""];
1504 break;
1505 case '\'':
1506 [destStr appendString:@"\\\'"];
1507 break;
1508 case '\\':
1509 [destStr appendString:@"\\\\"];
1510 break;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001511 default:
Thomas Van Lenten1a6c1d02016-08-08 18:02:43 -04001512 // This differs slightly from the C++ code in that the C++ doesn't
1513 // generate UTF8; it looks at the string in UTF8, but escapes every
1514 // byte > 0x7E.
1515 if (aChar < 0x20) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001516 [destStr appendFormat:@"\\%d%d%d", (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
Thomas Van Lenten1a6c1d02016-08-08 18:02:43 -04001517 } else {
1518 [destStr appendFormat:@"%C", aChar];
1519 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001520 break;
1521 }
1522 }
1523 [destStr appendString:@"\""];
1524}
1525
1526static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
1527 const char *src = (const char *)[buffer bytes];
1528 size_t srcLen = [buffer length];
1529 [destStr appendString:@"\""];
1530 for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
1531 switch (*src) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001532 case '\n':
1533 [destStr appendString:@"\\n"];
1534 break;
1535 case '\r':
1536 [destStr appendString:@"\\r"];
1537 break;
1538 case '\t':
1539 [destStr appendString:@"\\t"];
1540 break;
1541 case '\"':
1542 [destStr appendString:@"\\\""];
1543 break;
1544 case '\'':
1545 [destStr appendString:@"\\\'"];
1546 break;
1547 case '\\':
1548 [destStr appendString:@"\\\\"];
1549 break;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001550 default:
1551 if (isprint(*src)) {
1552 [destStr appendFormat:@"%c", *src];
1553 } else {
1554 // NOTE: doing hex means you have to worry about the letter after
1555 // the hex being another hex char and forcing that to be escaped, so
1556 // use octal to keep it simple.
1557 [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
1558 }
1559 break;
1560 }
1561 }
1562 [destStr appendString:@"\""];
1563}
1564
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001565static void AppendTextFormatForMapMessageField(id map, GPBFieldDescriptor *field,
1566 NSMutableString *toStr, NSString *lineIndent,
1567 NSString *fieldName, NSString *lineEnding) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001568 GPBDataType keyDataType = field.mapKeyDataType;
1569 GPBDataType valueDataType = GPBGetFieldDataType(field);
1570 BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001571
1572 NSString *msgStartFirst =
1573 [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001574 NSString *msgStart = [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001575 NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
1576
1577 NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent];
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001578 NSString *valueLine =
1579 [NSString stringWithFormat:@"%@ value%s ", lineIndent, (isMessageValue ? "" : ":")];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001580
1581 __block BOOL isFirst = YES;
1582
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001583 if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001584 // map is an NSDictionary.
1585 NSDictionary *dict = map;
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -04001586 [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, __unused BOOL *stop) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001587 [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
1588 isFirst = NO;
1589
1590 [toStr appendString:keyLine];
1591 AppendStringEscaped(key, toStr);
1592 [toStr appendString:@"\n"];
1593
1594 [toStr appendString:valueLine];
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001595#pragma clang diagnostic push
1596#pragma clang diagnostic ignored "-Wswitch-enum"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001597 switch (valueDataType) {
1598 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001599 AppendStringEscaped(value, toStr);
1600 break;
1601
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001602 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001603 AppendBufferAsString(value, toStr);
1604 break;
1605
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001606 case GPBDataTypeMessage:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001607 [toStr appendString:@"{\n"];
1608 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1609 AppendTextFormatForMessage(value, toStr, subIndent);
1610 [toStr appendFormat:@"%@ }", lineIndent];
1611 break;
1612
1613 default:
1614 NSCAssert(NO, @"Can't happen");
1615 break;
1616 }
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001617#pragma clang diagnostic pop
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001618 [toStr appendString:@"\n"];
1619
1620 [toStr appendString:msgEnd];
1621 }];
1622 } else {
1623 // map is one of the GPB*Dictionary classes, type doesn't matter.
1624 GPBInt32Int32Dictionary *dict = map;
1625 [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
1626 [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
1627 isFirst = NO;
1628
1629 // Key always is a NSString.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001630 if (keyDataType == GPBDataTypeString) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001631 [toStr appendString:keyLine];
1632 AppendStringEscaped(keyObj, toStr);
1633 [toStr appendString:@"\n"];
1634 } else {
1635 [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
1636 }
1637
1638 [toStr appendString:valueLine];
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001639#pragma clang diagnostic push
1640#pragma clang diagnostic ignored "-Wswitch-enum"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001641 switch (valueDataType) {
1642 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001643 AppendStringEscaped(valueObj, toStr);
1644 break;
1645
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001646 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001647 AppendBufferAsString(valueObj, toStr);
1648 break;
1649
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001650 case GPBDataTypeMessage:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001651 [toStr appendString:@"{\n"];
1652 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1653 AppendTextFormatForMessage(valueObj, toStr, subIndent);
1654 [toStr appendFormat:@"%@ }", lineIndent];
1655 break;
1656
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001657 case GPBDataTypeEnum: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001658 int32_t enumValue = [valueObj intValue];
1659 NSString *valueStr = nil;
1660 GPBEnumDescriptor *descriptor = field.enumDescriptor;
1661 if (descriptor) {
1662 valueStr = [descriptor textFormatNameForValue:enumValue];
1663 }
1664 if (valueStr) {
1665 [toStr appendString:valueStr];
1666 } else {
1667 [toStr appendFormat:@"%d", enumValue];
1668 }
1669 break;
1670 }
1671
1672 default:
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001673 NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001674 // Everything else is a NSString.
1675 [toStr appendString:valueObj];
1676 break;
1677 }
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001678#pragma clang diagnostic pop
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001679 [toStr appendString:@"\n"];
1680
1681 [toStr appendString:msgEnd];
1682 }];
1683 }
1684}
1685
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001686static void AppendTextFormatForMessageField(GPBMessage *message, GPBFieldDescriptor *field,
1687 NSMutableString *toStr, NSString *lineIndent) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001688 id arrayOrMap;
1689 NSUInteger count;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001690 GPBFieldType fieldType = field.fieldType;
1691 switch (fieldType) {
1692 case GPBFieldTypeSingle:
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001693 arrayOrMap = nil;
1694 count = (GPBGetHasIvarField(message, field) ? 1 : 0);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001695 break;
1696
1697 case GPBFieldTypeRepeated:
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001698 // Will be NSArray or GPB*Array, type doesn't matter, they both
1699 // implement count.
1700 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
1701 count = [(NSArray *)arrayOrMap count];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001702 break;
1703
1704 case GPBFieldTypeMap: {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001705 // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter,
1706 // they both implement count.
1707 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
1708 count = [(NSDictionary *)arrayOrMap count];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001709 break;
1710 }
1711 }
1712
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001713 if (count == 0) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001714 // Nothing to print, out of here.
1715 return;
1716 }
1717
1718 NSString *lineEnding = @"";
1719
1720 // If the name can't be reversed or support for extra info was turned off,
1721 // this can return nil.
1722 NSString *fieldName = [field textFormatName];
1723 if ([fieldName length] == 0) {
1724 fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
1725 // If there is only one entry, put the objc name as a comment, other wise
Dongjoon Hyun7a9040f2016-01-14 22:12:03 -08001726 // add it before the repeated values.
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001727 if (count > 1) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001728 [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
1729 } else {
1730 lineEnding = [NSString stringWithFormat:@" # %@", field.name];
1731 }
1732 }
1733
1734 if (fieldType == GPBFieldTypeMap) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001735 AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, fieldName, lineEnding);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001736 return;
1737 }
1738
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001739 id array = arrayOrMap;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001740 const BOOL isRepeated = (array != nil);
1741
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001742 GPBDataType fieldDataType = GPBGetFieldDataType(field);
1743 BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001744 for (NSUInteger j = 0; j < count; ++j) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001745 // Start the line.
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001746 [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, (isMessageField ? "" : ":")];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001747
1748 // The value.
1749 switch (fieldDataType) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001750#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \
1751 case GPBDataType##GPBDATATYPE: { \
1752 CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \
1753 : GPBGetMessage##REAL_TYPE##Field(message, field)); \
1754 [toStr appendFormat:__VA_ARGS__, v]; \
1755 break; \
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001756 }
1757
1758 FIELD_CASE(Int32, int32_t, Int32, @"%d")
1759 FIELD_CASE(SInt32, int32_t, Int32, @"%d")
1760 FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
1761 FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
1762 FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
1763 FIELD_CASE(Int64, int64_t, Int64, @"%lld")
1764 FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
1765 FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
1766 FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
1767 FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
1768 FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
1769 FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
1770
1771#undef FIELD_CASE
1772
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001773 case GPBDataTypeEnum: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001774 int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001775 : GPBGetMessageInt32Field(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001776 NSString *valueStr = nil;
1777 GPBEnumDescriptor *descriptor = field.enumDescriptor;
1778 if (descriptor) {
1779 valueStr = [descriptor textFormatNameForValue:v];
1780 }
1781 if (valueStr) {
1782 [toStr appendString:valueStr];
1783 } else {
1784 [toStr appendFormat:@"%d", v];
1785 }
1786 break;
1787 }
1788
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001789 case GPBDataTypeBool: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001790 BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001791 : GPBGetMessageBoolField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001792 [toStr appendString:(v ? @"true" : @"false")];
1793 break;
1794 }
1795
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001796 case GPBDataTypeString: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001797 NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001798 : GPBGetMessageStringField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001799 AppendStringEscaped(v, toStr);
1800 break;
1801 }
1802
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001803 case GPBDataTypeBytes: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001804 NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001805 : GPBGetMessageBytesField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001806 AppendBufferAsString(v, toStr);
1807 break;
1808 }
1809
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001810 case GPBDataTypeGroup:
1811 case GPBDataTypeMessage: {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001812 GPBMessage *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
1813 : GPBGetObjectIvarWithField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001814 [toStr appendFormat:@"{%@\n", lineEnding];
1815 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1816 AppendTextFormatForMessage(v, toStr, subIndent);
1817 [toStr appendFormat:@"%@}", lineIndent];
1818 lineEnding = @"";
1819 break;
1820 }
1821
1822 } // switch(fieldDataType)
1823
1824 // End the line.
1825 [toStr appendFormat:@"%@\n", lineEnding];
1826
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001827 } // for(count)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001828}
1829
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001830static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSArray *activeExtensions,
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001831 GPBExtensionRange range,
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001832 NSMutableString *toStr, NSString *lineIndent) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001833 uint32_t start = range.start;
1834 uint32_t end = range.end;
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001835 for (GPBExtensionDescriptor *extension in activeExtensions) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001836 uint32_t fieldNumber = extension.fieldNumber;
1837 if (fieldNumber < start) {
1838 // Not there yet.
1839 continue;
1840 }
Thomas Van Lentenaf2d4132018-11-14 16:09:43 -05001841 if (fieldNumber >= end) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001842 // Done.
1843 break;
1844 }
1845
1846 id rawExtValue = [message getExtension:extension];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001847 BOOL isRepeated = extension.isRepeated;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001848
1849 NSUInteger numValues = 1;
1850 NSString *lineEnding = @"";
1851 if (isRepeated) {
1852 numValues = [(NSArray *)rawExtValue count];
1853 }
1854
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001855 NSString *singletonName = extension.singletonName;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001856 if (numValues == 1) {
1857 lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName];
1858 } else {
1859 [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
1860 }
1861
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001862 GPBDataType extDataType = extension.dataType;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001863 for (NSUInteger j = 0; j < numValues; ++j) {
1864 id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
1865
1866 // Start the line.
1867 [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001868 (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001869
1870 // The value.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001871 switch (extDataType) {
1872#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
1873 case GPBDataType##GPBDATATYPE: { \
1874 CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \
1875 [toStr appendFormat:__VA_ARGS__, v]; \
1876 break; \
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001877 }
1878
1879 FIELD_CASE(Int32, int32_t, intValue, @"%d")
1880 FIELD_CASE(SInt32, int32_t, intValue, @"%d")
1881 FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
1882 FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
1883 FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
1884 FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
1885 FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
1886 FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
1887 FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
1888 FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
1889 FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
1890 FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
1891 // TODO: Add a comment with the enum name from enum descriptors
1892 // (might not be real value, so leave it as a comment, ObjC compiler
1893 // name mangles differently). Doesn't look like we actually generate
1894 // an enum descriptor reference like we do for normal fields, so this
1895 // will take a compiler change.
1896 FIELD_CASE(Enum, int32_t, intValue, @"%d")
1897
1898#undef FIELD_CASE
1899
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001900 case GPBDataTypeBool:
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001901 [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" : @"false")];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001902 break;
1903
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001904 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001905 AppendStringEscaped(curValue, toStr);
1906 break;
1907
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001908 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001909 AppendBufferAsString((NSData *)curValue, toStr);
1910 break;
1911
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001912 case GPBDataTypeGroup:
1913 case GPBDataTypeMessage: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001914 [toStr appendFormat:@"{%@\n", lineEnding];
1915 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1916 AppendTextFormatForMessage(curValue, toStr, subIndent);
1917 [toStr appendFormat:@"%@}", lineIndent];
1918 lineEnding = @"";
1919 break;
1920 }
1921
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001922 } // switch(extDataType)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001923
Thomas Van Lenten3eb28892018-11-14 15:20:13 -05001924 // End the line.
1925 [toStr appendFormat:@"%@\n", lineEnding];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001926
Thomas Van Lenten3eb28892018-11-14 15:20:13 -05001927 } // for(numValues)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001928
1929 } // for..in(activeExtensions)
1930}
1931
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001932static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001933 NSString *lineIndent) {
1934 GPBDescriptor *descriptor = [message descriptor];
1935 NSArray *fieldsArray = descriptor->fields_;
1936 NSUInteger fieldCount = fieldsArray.count;
1937 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
1938 NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001939 NSArray *activeExtensions =
1940 [[message extensionsCurrentlySet] sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001941 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
1942 if (i == fieldCount) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001943 AppendTextFormatForMessageExtensionRange(message, activeExtensions, extensionRanges[j++],
1944 toStr, lineIndent);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001945 } else if (j == extensionRangesCount ||
1946 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001947 AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, lineIndent);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001948 } else {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001949 AppendTextFormatForMessageExtensionRange(message, activeExtensions, extensionRanges[j++],
1950 toStr, lineIndent);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001951 }
1952 }
1953
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001954 NSString *unknownFieldsStr = GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001955 if ([unknownFieldsStr length] > 0) {
1956 [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
1957 [toStr appendString:unknownFieldsStr];
1958 }
1959}
1960
1961NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
Thomas Van Lenten8c889572015-06-16 16:45:14 -04001962 if (message == nil) return @"";
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001963 if (lineIndent == nil) lineIndent = @"";
1964
1965 NSMutableString *buildString = [NSMutableString string];
1966 AppendTextFormatForMessage(message, buildString, lineIndent);
1967 return buildString;
1968}
1969
Thomas Van Lenten189f6322022-09-19 17:21:13 -04001970NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, NSString *lineIndent) {
Thomas Van Lenten8c889572015-06-16 16:45:14 -04001971 if (unknownSet == nil) return @"";
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001972 if (lineIndent == nil) lineIndent = @"";
1973
1974 NSMutableString *result = [NSMutableString string];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001975 for (GPBUnknownField *field in [unknownSet sortedFields]) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001976 int32_t fieldNumber = [field number];
1977
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -04001978#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \
1979 [field.PROPNAME \
1980 enumerateValuesWithBlock:^(CTYPE value, __unused NSUInteger idx, __unused BOOL * stop) { \
1981 [result appendFormat:@"%@%d: " FORMAT "\n", lineIndent, fieldNumber, value]; \
1982 }];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001983
Thomas Van Lenten9e069b22022-09-19 13:34:01 -04001984 PRINT_LOOP(varintList, uint64_t, "%llu");
1985 PRINT_LOOP(fixed32List, uint32_t, "0x%X");
1986 PRINT_LOOP(fixed64List, uint64_t, "0x%llX");
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001987
1988#undef PRINT_LOOP
1989
1990 // NOTE: C++ version of TextFormat tries to parse this as a message
1991 // and print that if it succeeds.
1992 for (NSData *data in field.lengthDelimitedList) {
1993 [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
1994 AppendBufferAsString(data, result);
1995 [result appendString:@"\n"];
1996 }
1997
1998 for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
1999 [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
2000 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002001 NSString *subUnknownSetStr = GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
Tamarous6718fa92022-04-27 00:25:01 +08002002 [result appendString:subUnknownSetStr];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002003 [result appendFormat:@"%@}\n", lineIndent];
2004 }
2005 }
2006 return result;
2007}
2008
2009// Helpers to decode a varint. Not using GPBCodedInputStream version because
2010// that needs a state object, and we don't want to create an input stream out
2011// of the data.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04002012GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002013 int8_t result = *((int8_t *)(*data));
2014 ++(*data);
2015 return result;
2016}
2017
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04002018static int32_t ReadRawVarint32FromData(const uint8_t **data) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002019 int8_t tmp = ReadRawByteFromData(data);
2020 if (tmp >= 0) {
2021 return tmp;
2022 }
2023 int32_t result = tmp & 0x7f;
2024 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2025 result |= tmp << 7;
2026 } else {
2027 result |= (tmp & 0x7f) << 7;
2028 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2029 result |= tmp << 14;
2030 } else {
2031 result |= (tmp & 0x7f) << 14;
2032 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2033 result |= tmp << 21;
2034 } else {
2035 result |= (tmp & 0x7f) << 21;
2036 result |= (tmp = ReadRawByteFromData(data)) << 28;
2037 if (tmp < 0) {
2038 // Discard upper 32 bits.
2039 for (int i = 0; i < 5; i++) {
2040 if (ReadRawByteFromData(data) >= 0) {
2041 return result;
2042 }
2043 }
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002044 [NSException raise:NSParseErrorException format:@"Unable to read varint32"];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002045 }
2046 }
2047 }
2048 }
2049 return result;
2050}
2051
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002052NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputStr) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002053 // decodData form:
2054 // varint32: num entries
2055 // for each entry:
2056 // varint32: key
2057 // bytes*: decode data
2058 //
2059 // decode data one of two forms:
2060 // 1: a \0 followed by the string followed by an \0
2061 // 2: bytecodes to transform an input into the right thing, ending with \0
2062 //
2063 // the bytes codes are of the form:
2064 // 0xabbccccc
2065 // 0x0 (all zeros), end.
2066 // a - if set, add an underscore
2067 // bb - 00 ccccc bytes as is
2068 // bb - 10 ccccc upper first, as is on rest, ccccc byte total
2069 // bb - 01 ccccc lower first, as is on rest, ccccc byte total
2070 // bb - 11 ccccc all upper, ccccc byte total
2071
2072 if (!decodeData || !inputStr) {
2073 return nil;
2074 }
2075
2076 // Find key
2077 const uint8_t *scan = decodeData;
2078 int32_t numEntries = ReadRawVarint32FromData(&scan);
2079 BOOL foundKey = NO;
2080 while (!foundKey && (numEntries > 0)) {
2081 --numEntries;
2082 int32_t dataKey = ReadRawVarint32FromData(&scan);
2083 if (dataKey == key) {
2084 foundKey = YES;
2085 } else {
2086 // If it is a inlined string, it will start with \0; if it is bytecode it
2087 // will start with a code. So advance one (skipping the inline string
2088 // marker), and then loop until reaching the end marker (\0).
2089 ++scan;
2090 while (*scan != 0) ++scan;
2091 // Now move past the end marker.
2092 ++scan;
2093 }
2094 }
2095
2096 if (!foundKey) {
2097 return nil;
2098 }
2099
2100 // Decode
2101
2102 if (*scan == 0) {
2103 // Inline string. Move over the marker, and NSString can take it as
2104 // UTF8.
2105 ++scan;
2106 NSString *result = [NSString stringWithUTF8String:(const char *)scan];
2107 return result;
2108 }
2109
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002110 NSMutableString *result = [NSMutableString stringWithCapacity:[inputStr length]];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002111
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002112 const uint8_t kAddUnderscore = 0b10000000;
2113 const uint8_t kOpMask = 0b01100000;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002114 // const uint8_t kOpAsIs = 0b00000000;
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002115 const uint8_t kOpFirstUpper = 0b01000000;
2116 const uint8_t kOpFirstLower = 0b00100000;
2117 const uint8_t kOpAllUpper = 0b01100000;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002118 const uint8_t kSegmentLenMask = 0b00011111;
2119
2120 NSInteger i = 0;
2121 for (; *scan != 0; ++scan) {
2122 if (*scan & kAddUnderscore) {
2123 [result appendString:@"_"];
2124 }
2125 int segmentLen = *scan & kSegmentLenMask;
2126 uint8_t decodeOp = *scan & kOpMask;
2127
2128 // Do op specific handling of the first character.
2129 if (decodeOp == kOpFirstUpper) {
2130 unichar c = [inputStr characterAtIndex:i];
2131 [result appendFormat:@"%c", toupper((char)c)];
2132 ++i;
2133 --segmentLen;
2134 } else if (decodeOp == kOpFirstLower) {
2135 unichar c = [inputStr characterAtIndex:i];
2136 [result appendFormat:@"%c", tolower((char)c)];
2137 ++i;
2138 --segmentLen;
2139 }
2140 // else op == kOpAsIs || op == kOpAllUpper
2141
2142 // Now pull over the rest of the length for this segment.
2143 for (int x = 0; x < segmentLen; ++x) {
2144 unichar c = [inputStr characterAtIndex:(i + x)];
2145 if (decodeOp == kOpAllUpper) {
2146 [result appendFormat:@"%c", toupper((char)c)];
2147 } else {
2148 [result appendFormat:@"%C", c];
2149 }
2150 }
2151 i += segmentLen;
2152 }
2153
2154 return result;
2155}
2156
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04002157#pragma mark Legacy methods old generated code calls
2158
2159// Shim from the older generated code into the runtime.
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002160void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value,
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -04002161 __unused GPBFileSyntax syntax) {
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04002162 GPBSetMessageInt32Field(self, field, value);
2163}
2164
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002165void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, int32_t oneofHasIndex,
Thomas Van Lenten2fb33b82022-09-20 09:14:32 -04002166 __unused uint32_t fieldNumberNotToClear) {
Thomas Van Lenten189f6322022-09-19 17:21:13 -04002167#if defined(DEBUG) && DEBUG
2168 NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
2169 @"OneofDescriptor %@ doesn't appear to be for %@ messages.", oneof.name, [self class]);
2170 GPBFieldDescriptor *firstField __unused = oneof->fields_[0];
2171 NSCAssert(firstField->description_->hasIndex == oneofHasIndex,
2172 @"Internal error, oneofHasIndex (%d) doesn't match (%d).",
2173 firstField->description_->hasIndex, oneofHasIndex);
2174#endif
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04002175 GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0);
2176}
2177
2178#pragma clang diagnostic pop
2179
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04002180#pragma mark Misc Helpers
2181
Thomas Van Lenten2d1c5e22017-03-02 14:50:10 -05002182BOOL GPBClassHasSel(Class aClass, SEL sel) {
2183 // NOTE: We have to use class_copyMethodList, all other runtime method
2184 // lookups actually also resolve the method implementation and this
2185 // is called from within those methods.
2186
2187 BOOL result = NO;
2188 unsigned int methodCount = 0;
2189 Method *methodList = class_copyMethodList(aClass, &methodCount);
2190 for (unsigned int i = 0; i < methodCount; ++i) {
2191 SEL methodSelector = method_getName(methodList[i]);
2192 if (methodSelector == sel) {
2193 result = YES;
2194 break;
2195 }
2196 }
2197 free(methodList);
2198 return result;
2199}