blob: cd0910c5776f64a172264fb5d72f13081eb99989 [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.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "GPBUtilities_PackagePrivate.h"
32
33#import <objc/runtime.h>
34
35#import "GPBArray_PackagePrivate.h"
36#import "GPBDescriptor_PackagePrivate.h"
37#import "GPBDictionary_PackagePrivate.h"
Thomas Van Lenten30650d82015-05-01 08:57:16 -040038#import "GPBMessage_PackagePrivate.h"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -040039#import "GPBUnknownField.h"
Thomas Van Lenten30650d82015-05-01 08:57:16 -040040#import "GPBUnknownFieldSet.h"
41
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -040042// Direct access is use for speed, to avoid even internally declaring things
43// read/write, etc. The warning is enabled in the project to ensure code calling
44// protos can turn on -Wdirect-ivar-access without issues.
45#pragma clang diagnostic push
46#pragma clang diagnostic ignored "-Wdirect-ivar-access"
47
Thomas Van Lenten30650d82015-05-01 08:57:16 -040048static void AppendTextFormatForMessage(GPBMessage *message,
49 NSMutableString *toStr,
50 NSString *lineIndent);
51
dmaclach2b3aa1c2017-11-16 05:26:46 -080052// Are two datatypes the same basic type representation (ex Int32 and SInt32).
53// Marked unused because currently only called from asserts/debug.
54static BOOL DataTypesEquivalent(GPBDataType type1,
55 GPBDataType type2) __attribute__ ((unused));
56
57// Basic type representation for a type (ex: for SInt32 it is Int32).
58// Marked unused because currently only called from asserts/debug.
59static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused));
60
61// String name for a data type.
62// Marked unused because currently only called from asserts/debug.
63static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused));
64
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -040065// Helper for clearing oneofs.
66static void GPBMaybeClearOneofPrivate(GPBMessage *self,
67 GPBOneofDescriptor *oneof,
68 int32_t oneofHasIndex,
69 uint32_t fieldNumberNotToClear);
70
Thomas Van Lenten30650d82015-05-01 08:57:16 -040071NSData *GPBEmptyNSData(void) {
72 static dispatch_once_t onceToken;
73 static NSData *defaultNSData = nil;
74 dispatch_once(&onceToken, ^{
75 defaultNSData = [[NSData alloc] init];
76 });
77 return defaultNSData;
78}
79
Thomas Van Lentend0717662017-02-23 12:29:00 -050080void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) {
81 if (!initialMessage) {
82 return;
83 }
84
85 // Use an array as a list to process to avoid recursion.
86 NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage];
87
88 while (todo.count) {
89 GPBMessage *msg = todo.lastObject;
90 [todo removeLastObject];
91
92 // Clear unknowns.
93 msg.unknownFields = nil;
94
95 // Handle the message fields.
96 GPBDescriptor *descriptor = [[msg class] descriptor];
97 for (GPBFieldDescriptor *field in descriptor->fields_) {
98 if (!GPBFieldDataTypeIsMessage(field)) {
99 continue;
100 }
101 switch (field.fieldType) {
102 case GPBFieldTypeSingle:
103 if (GPBGetHasIvarField(msg, field)) {
104 GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
105 [todo addObject:fieldMessage];
106 }
107 break;
108
109 case GPBFieldTypeRepeated: {
110 NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
111 if (fieldMessages.count) {
112 [todo addObjectsFromArray:fieldMessages];
113 }
114 break;
115 }
116
117 case GPBFieldTypeMap: {
118 id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
119 switch (field.mapKeyDataType) {
120 case GPBDataTypeBool:
121 [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
122 BOOL key, id _Nonnull object, BOOL * _Nonnull stop) {
123 #pragma unused(key, stop)
124 [todo addObject:object];
125 }];
126 break;
127 case GPBDataTypeFixed32:
128 case GPBDataTypeUInt32:
129 [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
130 uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
131 #pragma unused(key, stop)
132 [todo addObject:object];
133 }];
134 break;
135 case GPBDataTypeInt32:
136 case GPBDataTypeSFixed32:
137 case GPBDataTypeSInt32:
138 [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
139 int32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
140 #pragma unused(key, stop)
141 [todo addObject:object];
142 }];
143 break;
144 case GPBDataTypeFixed64:
145 case GPBDataTypeUInt64:
146 [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
147 uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
148 #pragma unused(key, stop)
149 [todo addObject:object];
150 }];
151 break;
152 case GPBDataTypeInt64:
153 case GPBDataTypeSFixed64:
154 case GPBDataTypeSInt64:
155 [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
156 int64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
157 #pragma unused(key, stop)
158 [todo addObject:object];
159 }];
160 break;
161 case GPBDataTypeString:
162 [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
163 NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) {
164 #pragma unused(key, stop)
165 [todo addObject:obj];
166 }];
167 break;
168 case GPBDataTypeFloat:
169 case GPBDataTypeDouble:
170 case GPBDataTypeEnum:
171 case GPBDataTypeBytes:
172 case GPBDataTypeGroup:
173 case GPBDataTypeMessage:
174 NSCAssert(NO, @"Aren't valid key types.");
175 }
176 break;
177 } // switch(field.mapKeyDataType)
178 } // switch(field.fieldType)
179 } // for(fields)
180
181 // Handle any extensions holding messages.
182 for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) {
183 if (!GPBDataTypeIsMessage(extension.dataType)) {
184 continue;
185 }
186 if (extension.isRepeated) {
187 NSArray *extMessages = [msg getExtension:extension];
188 [todo addObjectsFromArray:extMessages];
189 } else {
190 GPBMessage *extMessage = [msg getExtension:extension];
191 [todo addObject:extMessage];
192 }
193 } // for(extensionsCurrentlySet)
194
195 } // while(todo.count)
196}
197
198
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400199// -- About Version Checks --
200// There's actually 3 places these checks all come into play:
201// 1. When the generated source is compile into .o files, the header check
202// happens. This is checking the protoc used matches the library being used
203// when making the .o.
204// 2. Every place a generated proto header is included in a developer's code,
205// the header check comes into play again. But this time it is checking that
206// the current library headers being used still support/match the ones for
207// the generated code.
208// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is
209// called from the generated code passing in values captured when the
210// generated code's .o was made. This checks that at runtime the generated
211// code and runtime library match.
212
213void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) {
214 // NOTE: This is passing the value captured in the compiled code to check
215 // against the values captured when the runtime support was compiled. This
216 // ensures the library code isn't in a different framework/library that
217 // was generated with a non matching version.
218 if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) {
219 // Library is too old for headers.
220 [NSException raise:NSInternalInconsistencyException
221 format:@"Linked to ProtocolBuffer runtime version %d,"
Peter Newmane2cc2de2020-08-10 19:08:25 +0100222 @" but code compiled needing at least %d!",
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400223 GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
224 }
225 if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
226 // Headers are too old for library.
227 [NSException raise:NSInternalInconsistencyException
228 format:@"Proto generation source compiled against runtime"
229 @" version %d, but this version of the runtime only"
230 @" supports back to %d!",
231 objcRuntimeVersion,
232 GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
233 }
234}
235
236// This api is no longer used for version checks. 30001 is the last version
237// using this old versioning model. When that support is removed, this function
238// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h).
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400239void GPBCheckRuntimeVersionInternal(int32_t version) {
Thomas Van Lenten1aa65002016-09-15 13:27:17 -0400240 GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001,
241 time_to_remove_this_old_version_shim);
242 if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400243 [NSException raise:NSInternalInconsistencyException
244 format:@"Linked to ProtocolBuffer runtime version %d,"
245 @" but code compiled with version %d!",
246 GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
247 }
248}
249
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400250BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
251 GPBDescriptor *descriptor = [self descriptor];
252 GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
253 return GPBMessageHasFieldSet(self, field);
254}
255
256BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
257 if (self == nil || field == nil) return NO;
258
259 // Repeated/Map don't use the bit, they check the count.
260 if (GPBFieldIsMapOrArray(field)) {
261 // Array/map type doesn't matter, since GPB*Array/NSArray and
262 // GPB*Dictionary/NSDictionary all support -count;
263 NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
264 return (arrayOrMap.count > 0);
265 } else {
266 return GPBGetHasIvarField(self, field);
267 }
268}
269
270void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
271 // If not set, nothing to do.
272 if (!GPBGetHasIvarField(self, field)) {
273 return;
274 }
275
Thomas Van Lenten95282462020-04-07 14:43:13 -0400276 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400277 if (GPBFieldStoresObject(field)) {
278 // Object types are handled slightly differently, they need to be released.
279 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400280 id *typePtr = (id *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400281 [*typePtr release];
282 *typePtr = nil;
283 } else {
284 // POD types just need to clear the has bit as the Get* method will
285 // fetch the default when needed.
286 }
Thomas Van Lenten95282462020-04-07 14:43:13 -0400287 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400288}
289
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400290void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) {
291 #if defined(DEBUG) && DEBUG
292 NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
293 @"OneofDescriptor %@ doesn't appear to be for %@ messages.",
294 oneof.name, [self class]);
295 #endif
296 GPBFieldDescriptor *firstField = oneof->fields_[0];
297 GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0);
298}
299
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400300BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400301 NSCAssert(self->messageStorage_ != NULL,
302 @"%@: All messages should have storage (from init)",
303 [self class]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400304 if (idx < 0) {
305 NSCAssert(fieldNumber != 0, @"Invalid field number.");
306 BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
307 return hasIvar;
308 } else {
309 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
310 uint32_t byteIndex = idx / 32;
Thomas Van Lenten953adb12018-01-31 11:59:57 -0500311 uint32_t bitMask = (1U << (idx % 32));
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400312 BOOL hasIvar =
313 (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
314 return hasIvar;
315 }
316}
317
318uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400319 NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.",
320 [self class], idx);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400321 uint32_t result = self->messageStorage_->_has_storage_[-idx];
322 return result;
323}
324
325void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
326 BOOL value) {
327 if (idx < 0) {
328 NSCAssert(fieldNumber != 0, @"Invalid field number.");
329 uint32_t *has_storage = self->messageStorage_->_has_storage_;
330 has_storage[-idx] = (value ? fieldNumber : 0);
331 } else {
332 NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
333 uint32_t *has_storage = self->messageStorage_->_has_storage_;
334 uint32_t byte = idx / 32;
Thomas Van Lenten953adb12018-01-31 11:59:57 -0500335 uint32_t bitMask = (1U << (idx % 32));
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400336 if (value) {
337 has_storage[byte] |= bitMask;
338 } else {
339 has_storage[byte] &= ~bitMask;
340 }
341 }
342}
343
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400344static void GPBMaybeClearOneofPrivate(GPBMessage *self,
345 GPBOneofDescriptor *oneof,
346 int32_t oneofHasIndex,
347 uint32_t fieldNumberNotToClear) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400348 uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400349 if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
350 // Do nothing/nothing set in the oneof.
351 return;
352 }
353
354 // Like GPBClearMessageField(), free the memory if an objecttype is set,
355 // pod types don't need to do anything.
356 GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400357 NSCAssert(fieldSet,
358 @"%@: oneof set to something (%u) not in the oneof?",
359 [self class], fieldNumberSet);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400360 if (fieldSet && GPBFieldStoresObject(fieldSet)) {
361 uint8_t *storage = (uint8_t *)self->messageStorage_;
362 id *typePtr = (id *)&storage[fieldSet->description_->offset];
363 [*typePtr release];
364 *typePtr = nil;
365 }
366
367 // Set to nothing stored in the oneof.
368 // (field number doesn't matter since setting to nothing).
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400369 GPBSetHasIvar(self, oneofHasIndex, 1, NO);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400370}
371
372#pragma mark - IVar accessors
373
374//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400375//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
376//% TYPE$S NAME$S GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800377//%#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400378//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
379//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
380//% field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800381//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
382//% GPBDataType##NAME),
383//% @"Attempting to get value of TYPE from field %@ "
384//% @"of %@ which is of type %@.",
385//% [self class], field.name,
386//% TypeToString(GPBGetFieldDataType(field)));
387//%#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400388//% if (GPBGetHasIvarField(self, field)) {
389//% uint8_t *storage = (uint8_t *)self->messageStorage_;
390//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
391//% return *typePtr;
392//% } else {
393//% return field.defaultValue.value##NAME;
394//% }
395//%}
396//%
397//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400398//%void GPBSetMessage##NAME##Field(GPBMessage *self,
399//% NAME$S GPBFieldDescriptor *field,
400//% NAME$S TYPE value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400401//% if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400402//%#if defined(DEBUG) && DEBUG
403//% NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
404//% @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
405//% field.name, [self class]);
406//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
407//% GPBDataType##NAME),
408//% @"Attempting to set field %@ of %@ which is of type %@ with "
409//% @"value of type TYPE.",
410//% [self class], field.name,
411//% TypeToString(GPBGetFieldDataType(field)));
412//%#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400413//% GPBSet##NAME##IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400414//%}
415//%
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400416//%void GPBSet##NAME##IvarWithFieldPrivate(GPBMessage *self,
417//% NAME$S GPBFieldDescriptor *field,
418//% NAME$S TYPE value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400419//% GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400420//% GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400421//% if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400422//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400423//% }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800424//%#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400425//% NSCAssert(self->messageStorage_ != NULL,
426//% @"%@: All messages should have storage (from init)",
427//% [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800428//%#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400429//%#if defined(__clang_analyzer__)
430//% if (self->messageStorage_ == NULL) return;
431//%#endif
432//% uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400433//% TYPE *typePtr = (TYPE *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400434//% *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400435//% // If the value is zero, then we only count the field as "set" if the field
436//% // shouldn't auto clear on zero.
437//% BOOL hasValue = ((value != (TYPE)0)
438//% || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400439//% GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400440//% GPBBecomeVisibleToAutocreator(self);
441//%}
442//%
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400443//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400444//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400445//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
446//% TYPE$S NAME$S GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800447//%#if defined(DEBUG) && DEBUG
448//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
449//% GPBDataType##NAME),
450//% @"Attempting to get value of TYPE from field %@ "
451//% @"of %@ which is of type %@.",
452//% [self class], field.name,
453//% TypeToString(GPBGetFieldDataType(field)));
454//%#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400455//% return (TYPE *)GPBGetObjectIvarWithField(self, field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400456//%}
457//%
458//%// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400459//%void GPBSetMessage##NAME##Field(GPBMessage *self,
460//% NAME$S GPBFieldDescriptor *field,
461//% NAME$S TYPE *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800462//%#if defined(DEBUG) && DEBUG
463//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
464//% GPBDataType##NAME),
465//% @"Attempting to set field %@ of %@ which is of type %@ with "
466//% @"value of type TYPE.",
467//% [self class], field.name,
468//% TypeToString(GPBGetFieldDataType(field)));
469//%#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400470//% GPBSetObjectIvarWithField(self, field, (id)value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400471//%}
472//%
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400473//%PDDM-DEFINE IVAR_ALIAS_DEFN_COPY_OBJECT(NAME, TYPE)
474//%// Only exists for public api, no core code should use this.
475//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
476//% TYPE$S NAME$S GPBFieldDescriptor *field) {
477//%#if defined(DEBUG) && DEBUG
478//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
479//% GPBDataType##NAME),
480//% @"Attempting to get value of TYPE from field %@ "
481//% @"of %@ which is of type %@.",
482//% [self class], field.name,
483//% TypeToString(GPBGetFieldDataType(field)));
484//%#endif
485//% return (TYPE *)GPBGetObjectIvarWithField(self, field);
486//%}
487//%
488//%// Only exists for public api, no core code should use this.
489//%void GPBSetMessage##NAME##Field(GPBMessage *self,
490//% NAME$S GPBFieldDescriptor *field,
491//% NAME$S TYPE *value) {
492//%#if defined(DEBUG) && DEBUG
493//% NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
494//% GPBDataType##NAME),
495//% @"Attempting to set field %@ of %@ which is of type %@ with "
496//% @"value of type TYPE.",
497//% [self class], field.name,
498//% TypeToString(GPBGetFieldDataType(field)));
499//%#endif
500//% GPBSetCopyObjectIvarWithField(self, field, (id)value);
501//%}
502//%
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400503
504// Object types are handled slightly differently, they need to be released
505// and retained.
506
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400507void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
508 GPBFieldDescriptor *field) {
509 if (GPBGetHasIvarField(self, field)) {
510 return;
511 }
512 uint8_t *storage = (uint8_t *)self->messageStorage_;
513 id *typePtr = (id *)&storage[field->description_->offset];
514 GPBMessage *oldValue = *typePtr;
515 *typePtr = NULL;
516 GPBClearMessageAutocreator(oldValue);
517 [oldValue release];
518}
519
Brian Wignalla104dff2020-01-08 13:18:20 -0500520// This exists only for bridging some aliased types, nothing else should use it.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400521static void GPBSetObjectIvarWithField(GPBMessage *self,
522 GPBFieldDescriptor *field, id value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400523 if (self == nil || field == nil) return;
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400524 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400525}
526
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400527static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
528 GPBFieldDescriptor *field, id value);
529
530// GPBSetCopyObjectIvarWithField is blocked from the analyzer because it flags
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400531// a leak for the -copy even though GPBSetRetainedObjectIvarWithFieldPrivate
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400532// is marked as consuming the value. Note: For some reason this doesn't happen
533// with the -retain in GPBSetObjectIvarWithField.
534#if !defined(__clang_analyzer__)
Brian Wignalla104dff2020-01-08 13:18:20 -0500535// This exists only for bridging some aliased types, nothing else should use it.
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400536static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
537 GPBFieldDescriptor *field, id value) {
538 if (self == nil || field == nil) return;
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400539 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]);
Thomas Van Lenten09c001e2018-10-02 10:42:55 -0400540}
541#endif // !defined(__clang_analyzer__)
542
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400543void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
544 GPBFieldDescriptor *field, id value) {
545 GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400546}
547
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400548void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
549 GPBFieldDescriptor *field,
550 id value) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400551 NSCAssert(self->messageStorage_ != NULL,
552 @"%@: All messages should have storage (from init)",
553 [self class]);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400554#if defined(__clang_analyzer__)
555 if (self->messageStorage_ == NULL) return;
556#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400557 GPBDataType fieldType = GPBGetFieldDataType(field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400558 BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400559 BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800560#if defined(DEBUG) && DEBUG
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400561 if (value == nil && !isMapOrArray && !fieldIsMessage &&
562 field.hasDefaultValue) {
563 // Setting a message to nil is an obvious way to "clear" the value
564 // as there is no way to set a non-empty default value for messages.
565 //
566 // For Strings and Bytes that have default values set it is not clear what
567 // should be done when their value is set to nil. Is the intention just to
568 // clear the set value and reset to default, or is the intention to set the
569 // value to the empty string/data? Arguments can be made for both cases.
570 // 'nil' has been abused as a replacement for an empty string/data in ObjC.
571 // We decided to be consistent with all "object" types and clear the has
572 // field, and fall back on the default value. The warning below will only
573 // appear in debug, but the could should be changed so the intention is
574 // clear.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400575 NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400576 NSString *propName = field.name;
577 NSString *className = self.descriptor.name;
578 NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
579 @"default values. Please use '%@.%@ = %@' if you want to set it to "
580 @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
581 @"'%@'. Defaulting to resetting default value.",
582 className, propName, className, propName,
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400583 (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400584 className, hasSel, field.defaultValue.valueString);
585 // Note: valueString, depending on the type, it could easily be
586 // valueData/valueMessage.
587 }
588#endif // DEBUG
Thomas Van Lenten95282462020-04-07 14:43:13 -0400589 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400590 if (!isMapOrArray) {
591 // Non repeated/map can be in an oneof, clear any existing value from the
592 // oneof.
593 GPBOneofDescriptor *oneof = field->containingOneof_;
594 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400595 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400596 }
597 // Clear "has" if they are being set to nil.
598 BOOL setHasValue = (value != nil);
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400599 // If the field should clear on a "zero" value, then check if the string/data
600 // was zero length, and clear instead.
601 if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) &&
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400602 ([value length] == 0)) {
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400603 setHasValue = NO;
604 // The value passed in was retained, it must be released since we
605 // aren't saving anything in the field.
606 [value release];
607 value = nil;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400608 }
Thomas Van Lenten95282462020-04-07 14:43:13 -0400609 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, setHasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400610 }
611 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400612 id *typePtr = (id *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400613
614 id oldValue = *typePtr;
615
616 *typePtr = value;
617
618 if (oldValue) {
619 if (isMapOrArray) {
620 if (field.fieldType == GPBFieldTypeRepeated) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400621 // If the old array was autocreated by us, then clear it.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400622 if (GPBDataTypeIsObject(fieldType)) {
Thomas Van Lenten988ffe02017-01-04 15:03:42 -0500623 if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) {
624 GPBAutocreatedArray *autoArray = oldValue;
625 if (autoArray->_autocreator == self) {
626 autoArray->_autocreator = nil;
627 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400628 }
629 } else {
630 // Type doesn't matter, it is a GPB*Array.
631 GPBInt32Array *gpbArray = oldValue;
632 if (gpbArray->_autocreator == self) {
633 gpbArray->_autocreator = nil;
634 }
635 }
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400636 } else { // GPBFieldTypeMap
637 // If the old map was autocreated by us, then clear it.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400638 if ((field.mapKeyDataType == GPBDataTypeString) &&
639 GPBDataTypeIsObject(fieldType)) {
Thomas Van Lenten988ffe02017-01-04 15:03:42 -0500640 if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
641 GPBAutocreatedDictionary *autoDict = oldValue;
642 if (autoDict->_autocreator == self) {
643 autoDict->_autocreator = nil;
644 }
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400645 }
646 } else {
647 // Type doesn't matter, it is a GPB*Dictionary.
648 GPBInt32Int32Dictionary *gpbDict = oldValue;
649 if (gpbDict->_autocreator == self) {
650 gpbDict->_autocreator = nil;
651 }
652 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400653 }
654 } else if (fieldIsMessage) {
655 // If the old message value was autocreated by us, then clear it.
656 GPBMessage *oldMessageValue = oldValue;
657 if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
658 GPBClearMessageAutocreator(oldMessageValue);
659 }
660 }
661 [oldValue release];
662 }
663
664 GPBBecomeVisibleToAutocreator(self);
665}
666
667id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
668 GPBFieldDescriptor *field) {
669 if (self->messageStorage_ == nil) {
670 return nil;
671 }
672 uint8_t *storage = (uint8_t *)self->messageStorage_;
673 id *typePtr = (id *)&storage[field->description_->offset];
674 return *typePtr;
675}
676
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400677// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400678int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400679 #if defined(DEBUG) && DEBUG
680 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
681 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
682 field.name, [self class]);
683 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
684 @"Attempting to get value of type Enum from field %@ "
685 @"of %@ which is of type %@.",
686 [self class], field.name,
687 TypeToString(GPBGetFieldDataType(field)));
688 #endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400689
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400690 int32_t result = GPBGetMessageInt32Field(self, field);
691 // If this is presevering unknown enums, make sure the value is valid before
692 // returning it.
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400693
694 GPBFileSyntax syntax = [self descriptor].file.syntax;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400695 if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
696 ![field isValidEnumValue:result]) {
697 result = kGPBUnrecognizedEnumeratorValue;
698 }
699 return result;
700}
701
702// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400703void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
704 int32_t value) {
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400705 #if defined(DEBUG) && DEBUG
706 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
707 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
708 field.name, [self class]);
709 NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
710 @"Attempting to set field %@ of %@ which is of type %@ with "
711 @"value of type Enum.",
712 [self class], field.name,
713 TypeToString(GPBGetFieldDataType(field)));
714 #endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400715 GPBSetEnumIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400716}
717
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400718void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
719 GPBFieldDescriptor *field, int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400720 // Don't allow in unknown values. Proto3 can use the Raw method.
721 if (![field isValidEnumValue:value]) {
722 [NSException raise:NSInvalidArgumentException
723 format:@"%@.%@: Attempt to set an unknown enum value (%d)",
724 [self class], field.name, value];
725 }
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400726 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400727}
728
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400729// Only exists for public api, no core code should use this.
730int32_t GPBGetMessageRawEnumField(GPBMessage *self,
731 GPBFieldDescriptor *field) {
732 int32_t result = GPBGetMessageInt32Field(self, field);
733 return result;
734}
735
736// Only exists for public api, no core code should use this.
737void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
738 int32_t value) {
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400739 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400740}
741
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400742BOOL GPBGetMessageBoolField(GPBMessage *self,
743 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800744#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400745 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
746 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
747 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800748 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
749 @"Attempting to get value of type bool from field %@ "
750 @"of %@ which is of type %@.",
751 [self class], field.name,
752 TypeToString(GPBGetFieldDataType(field)));
753#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400754 if (GPBGetHasIvarField(self, field)) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400755 // Bools are stored in the has bits to avoid needing explicit space in the
756 // storage structure.
757 // (the field number passed to the HasIvar helper doesn't really matter
758 // since the offset is never negative)
759 GPBMessageFieldDescription *fieldDesc = field->description_;
760 return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400761 } else {
762 return field.defaultValue.valueBool;
763 }
764}
765
766// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400767void GPBSetMessageBoolField(GPBMessage *self,
768 GPBFieldDescriptor *field,
769 BOOL value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400770 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400771 #if defined(DEBUG) && DEBUG
772 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
773 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
774 field.name, [self class]);
775 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
776 @"Attempting to set field %@ of %@ which is of type %@ with "
777 @"value of type bool.",
778 [self class], field.name,
779 TypeToString(GPBGetFieldDataType(field)));
780 #endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400781 GPBSetBoolIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400782}
783
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400784void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
785 GPBFieldDescriptor *field,
786 BOOL value) {
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400787 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400788 GPBOneofDescriptor *oneof = field->containingOneof_;
789 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400790 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400791 }
Thomas Van Lenten79a23c42016-03-17 10:04:21 -0400792
793 // Bools are stored in the has bits to avoid needing explicit space in the
794 // storage structure.
795 // (the field number passed to the HasIvar helper doesn't really matter since
796 // the offset is never negative)
797 GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
798
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400799 // If the value is zero, then we only count the field as "set" if the field
800 // shouldn't auto clear on zero.
801 BOOL hasValue = ((value != (BOOL)0)
802 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400803 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400804 GPBBecomeVisibleToAutocreator(self);
805}
806
807//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
808// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800809// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400810
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400811int32_t GPBGetMessageInt32Field(GPBMessage *self,
812 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800813#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400814 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
815 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
816 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800817 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
818 GPBDataTypeInt32),
819 @"Attempting to get value of int32_t from field %@ "
820 @"of %@ which is of type %@.",
821 [self class], field.name,
822 TypeToString(GPBGetFieldDataType(field)));
823#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400824 if (GPBGetHasIvarField(self, field)) {
825 uint8_t *storage = (uint8_t *)self->messageStorage_;
826 int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
827 return *typePtr;
828 } else {
829 return field.defaultValue.valueInt32;
830 }
831}
832
833// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400834void GPBSetMessageInt32Field(GPBMessage *self,
835 GPBFieldDescriptor *field,
836 int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400837 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400838#if defined(DEBUG) && DEBUG
839 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
840 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
841 field.name, [self class]);
842 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
843 GPBDataTypeInt32),
844 @"Attempting to set field %@ of %@ which is of type %@ with "
845 @"value of type int32_t.",
846 [self class], field.name,
847 TypeToString(GPBGetFieldDataType(field)));
848#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400849 GPBSetInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400850}
851
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400852void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self,
853 GPBFieldDescriptor *field,
854 int32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400855 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400856 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400857 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400858 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400859 }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800860#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400861 NSCAssert(self->messageStorage_ != NULL,
862 @"%@: All messages should have storage (from init)",
863 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800864#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400865#if defined(__clang_analyzer__)
866 if (self->messageStorage_ == NULL) return;
867#endif
868 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400869 int32_t *typePtr = (int32_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400870 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400871 // If the value is zero, then we only count the field as "set" if the field
872 // shouldn't auto clear on zero.
873 BOOL hasValue = ((value != (int32_t)0)
874 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400875 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400876 GPBBecomeVisibleToAutocreator(self);
877}
878
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800879// clang-format on
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400880//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
881// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800882// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400883
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400884uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
885 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800886#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400887 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
888 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
889 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800890 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
891 GPBDataTypeUInt32),
892 @"Attempting to get value of uint32_t from field %@ "
893 @"of %@ which is of type %@.",
894 [self class], field.name,
895 TypeToString(GPBGetFieldDataType(field)));
896#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400897 if (GPBGetHasIvarField(self, field)) {
898 uint8_t *storage = (uint8_t *)self->messageStorage_;
899 uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
900 return *typePtr;
901 } else {
902 return field.defaultValue.valueUInt32;
903 }
904}
905
906// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400907void GPBSetMessageUInt32Field(GPBMessage *self,
908 GPBFieldDescriptor *field,
909 uint32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400910 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400911#if defined(DEBUG) && DEBUG
912 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
913 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
914 field.name, [self class]);
915 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
916 GPBDataTypeUInt32),
917 @"Attempting to set field %@ of %@ which is of type %@ with "
918 @"value of type uint32_t.",
919 [self class], field.name,
920 TypeToString(GPBGetFieldDataType(field)));
921#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400922 GPBSetUInt32IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400923}
924
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400925void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self,
926 GPBFieldDescriptor *field,
927 uint32_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400928 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400929 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400930 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -0400931 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400932 }
dmaclach2b3aa1c2017-11-16 05:26:46 -0800933#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -0400934 NSCAssert(self->messageStorage_ != NULL,
935 @"%@: All messages should have storage (from init)",
936 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800937#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400938#if defined(__clang_analyzer__)
939 if (self->messageStorage_ == NULL) return;
940#endif
941 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -0400942 uint32_t *typePtr = (uint32_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400943 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -0400944 // If the value is zero, then we only count the field as "set" if the field
945 // shouldn't auto clear on zero.
946 BOOL hasValue = ((value != (uint32_t)0)
947 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -0400948 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400949 GPBBecomeVisibleToAutocreator(self);
950}
951
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800952// clang-format on
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400953//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
954// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -0800955// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400956
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400957int64_t GPBGetMessageInt64Field(GPBMessage *self,
958 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -0800959#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400960 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
961 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
962 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -0800963 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
964 GPBDataTypeInt64),
965 @"Attempting to get value of int64_t from field %@ "
966 @"of %@ which is of type %@.",
967 [self class], field.name,
968 TypeToString(GPBGetFieldDataType(field)));
969#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400970 if (GPBGetHasIvarField(self, field)) {
971 uint8_t *storage = (uint8_t *)self->messageStorage_;
972 int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
973 return *typePtr;
974 } else {
975 return field.defaultValue.valueInt64;
976 }
977}
978
979// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -0400980void GPBSetMessageInt64Field(GPBMessage *self,
981 GPBFieldDescriptor *field,
982 int64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400983 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -0400984#if defined(DEBUG) && DEBUG
985 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
986 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
987 field.name, [self class]);
988 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
989 GPBDataTypeInt64),
990 @"Attempting to set field %@ of %@ which is of type %@ with "
991 @"value of type int64_t.",
992 [self class], field.name,
993 TypeToString(GPBGetFieldDataType(field)));
994#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400995 GPBSetInt64IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -0400996}
997
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -0400998void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self,
999 GPBFieldDescriptor *field,
1000 int64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001001 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001002 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001003 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001004 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001005 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001006#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001007 NSCAssert(self->messageStorage_ != NULL,
1008 @"%@: All messages should have storage (from init)",
1009 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001010#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001011#if defined(__clang_analyzer__)
1012 if (self->messageStorage_ == NULL) return;
1013#endif
1014 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001015 int64_t *typePtr = (int64_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001016 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001017 // If the value is zero, then we only count the field as "set" if the field
1018 // shouldn't auto clear on zero.
1019 BOOL hasValue = ((value != (int64_t)0)
1020 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001021 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001022 GPBBecomeVisibleToAutocreator(self);
1023}
1024
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001025// clang-format on
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001026//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
1027// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001028// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001029
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001030uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
1031 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001032#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001033 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1034 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1035 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001036 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1037 GPBDataTypeUInt64),
1038 @"Attempting to get value of uint64_t from field %@ "
1039 @"of %@ which is of type %@.",
1040 [self class], field.name,
1041 TypeToString(GPBGetFieldDataType(field)));
1042#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001043 if (GPBGetHasIvarField(self, field)) {
1044 uint8_t *storage = (uint8_t *)self->messageStorage_;
1045 uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
1046 return *typePtr;
1047 } else {
1048 return field.defaultValue.valueUInt64;
1049 }
1050}
1051
1052// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001053void GPBSetMessageUInt64Field(GPBMessage *self,
1054 GPBFieldDescriptor *field,
1055 uint64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001056 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001057#if defined(DEBUG) && DEBUG
1058 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1059 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1060 field.name, [self class]);
1061 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1062 GPBDataTypeUInt64),
1063 @"Attempting to set field %@ of %@ which is of type %@ with "
1064 @"value of type uint64_t.",
1065 [self class], field.name,
1066 TypeToString(GPBGetFieldDataType(field)));
1067#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001068 GPBSetUInt64IvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001069}
1070
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001071void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self,
1072 GPBFieldDescriptor *field,
1073 uint64_t value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001074 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001075 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001076 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001077 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001078 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001079#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001080 NSCAssert(self->messageStorage_ != NULL,
1081 @"%@: All messages should have storage (from init)",
1082 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001083#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001084#if defined(__clang_analyzer__)
1085 if (self->messageStorage_ == NULL) return;
1086#endif
1087 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001088 uint64_t *typePtr = (uint64_t *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001089 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001090 // If the value is zero, then we only count the field as "set" if the field
1091 // shouldn't auto clear on zero.
1092 BOOL hasValue = ((value != (uint64_t)0)
1093 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001094 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001095 GPBBecomeVisibleToAutocreator(self);
1096}
1097
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001098// clang-format on
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001099//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
1100// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001101// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001102
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001103float GPBGetMessageFloatField(GPBMessage *self,
1104 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001105#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001106 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1107 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1108 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001109 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1110 GPBDataTypeFloat),
1111 @"Attempting to get value of float from field %@ "
1112 @"of %@ which is of type %@.",
1113 [self class], field.name,
1114 TypeToString(GPBGetFieldDataType(field)));
1115#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001116 if (GPBGetHasIvarField(self, field)) {
1117 uint8_t *storage = (uint8_t *)self->messageStorage_;
1118 float *typePtr = (float *)&storage[field->description_->offset];
1119 return *typePtr;
1120 } else {
1121 return field.defaultValue.valueFloat;
1122 }
1123}
1124
1125// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001126void GPBSetMessageFloatField(GPBMessage *self,
1127 GPBFieldDescriptor *field,
1128 float value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001129 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001130#if defined(DEBUG) && DEBUG
1131 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1132 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1133 field.name, [self class]);
1134 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1135 GPBDataTypeFloat),
1136 @"Attempting to set field %@ of %@ which is of type %@ with "
1137 @"value of type float.",
1138 [self class], field.name,
1139 TypeToString(GPBGetFieldDataType(field)));
1140#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001141 GPBSetFloatIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001142}
1143
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001144void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self,
1145 GPBFieldDescriptor *field,
1146 float value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001147 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001148 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001149 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001150 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001151 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001152#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001153 NSCAssert(self->messageStorage_ != NULL,
1154 @"%@: All messages should have storage (from init)",
1155 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001156#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001157#if defined(__clang_analyzer__)
1158 if (self->messageStorage_ == NULL) return;
1159#endif
1160 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001161 float *typePtr = (float *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001162 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001163 // If the value is zero, then we only count the field as "set" if the field
1164 // shouldn't auto clear on zero.
1165 BOOL hasValue = ((value != (float)0)
1166 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001167 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001168 GPBBecomeVisibleToAutocreator(self);
1169}
1170
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001171// clang-format on
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001172//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
1173// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001174// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001175
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001176double GPBGetMessageDoubleField(GPBMessage *self,
1177 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001178#if defined(DEBUG) && DEBUG
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001179 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1180 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1181 field.name, [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001182 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1183 GPBDataTypeDouble),
1184 @"Attempting to get value of double from field %@ "
1185 @"of %@ which is of type %@.",
1186 [self class], field.name,
1187 TypeToString(GPBGetFieldDataType(field)));
1188#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001189 if (GPBGetHasIvarField(self, field)) {
1190 uint8_t *storage = (uint8_t *)self->messageStorage_;
1191 double *typePtr = (double *)&storage[field->description_->offset];
1192 return *typePtr;
1193 } else {
1194 return field.defaultValue.valueDouble;
1195 }
1196}
1197
1198// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001199void GPBSetMessageDoubleField(GPBMessage *self,
1200 GPBFieldDescriptor *field,
1201 double value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001202 if (self == nil || field == nil) return;
Thomas Van Lenten7b8a2412020-04-08 13:14:38 -04001203#if defined(DEBUG) && DEBUG
1204 NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
1205 @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
1206 field.name, [self class]);
1207 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1208 GPBDataTypeDouble),
1209 @"Attempting to set field %@ of %@ which is of type %@ with "
1210 @"value of type double.",
1211 [self class], field.name,
1212 TypeToString(GPBGetFieldDataType(field)));
1213#endif
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001214 GPBSetDoubleIvarWithFieldPrivate(self, field, value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001215}
1216
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04001217void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
1218 GPBFieldDescriptor *field,
1219 double value) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001220 GPBOneofDescriptor *oneof = field->containingOneof_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001221 GPBMessageFieldDescription *fieldDesc = field->description_;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001222 if (oneof) {
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04001223 GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001224 }
dmaclach2b3aa1c2017-11-16 05:26:46 -08001225#if defined(DEBUG) && DEBUG
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001226 NSCAssert(self->messageStorage_ != NULL,
1227 @"%@: All messages should have storage (from init)",
1228 [self class]);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001229#endif
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001230#if defined(__clang_analyzer__)
1231 if (self->messageStorage_ == NULL) return;
1232#endif
1233 uint8_t *storage = (uint8_t *)self->messageStorage_;
Thomas Van Lenten95282462020-04-07 14:43:13 -04001234 double *typePtr = (double *)&storage[fieldDesc->offset];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001235 *typePtr = value;
Thomas Van Lenten8d224b42020-04-08 11:34:37 -04001236 // If the value is zero, then we only count the field as "set" if the field
1237 // shouldn't auto clear on zero.
1238 BOOL hasValue = ((value != (double)0)
1239 || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
Thomas Van Lenten95282462020-04-07 14:43:13 -04001240 GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001241 GPBBecomeVisibleToAutocreator(self);
1242}
1243
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001244// clang-format on
Thomas Van Lenten79a23c42016-03-17 10:04:21 -04001245//%PDDM-EXPAND-END (6 expansions)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001246
1247// Aliases are function calls that are virtually the same.
1248
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001249//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001250// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001251// clang-format off
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001252
1253// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001254NSString *GPBGetMessageStringField(GPBMessage *self,
1255 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001256#if defined(DEBUG) && DEBUG
1257 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1258 GPBDataTypeString),
1259 @"Attempting to get value of NSString from field %@ "
1260 @"of %@ which is of type %@.",
1261 [self class], field.name,
1262 TypeToString(GPBGetFieldDataType(field)));
1263#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001264 return (NSString *)GPBGetObjectIvarWithField(self, field);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001265}
1266
1267// Only exists for public api, no core code should use this.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001268void GPBSetMessageStringField(GPBMessage *self,
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001269 GPBFieldDescriptor *field,
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001270 NSString *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001271#if defined(DEBUG) && DEBUG
1272 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1273 GPBDataTypeString),
1274 @"Attempting to set field %@ of %@ which is of type %@ with "
1275 @"value of type NSString.",
1276 [self class], field.name,
1277 TypeToString(GPBGetFieldDataType(field)));
1278#endif
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001279 GPBSetCopyObjectIvarWithField(self, field, (id)value);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001280}
1281
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001282// clang-format on
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001283//%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData)
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001284// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001285// clang-format off
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001286
1287// Only exists for public api, no core code should use this.
1288NSData *GPBGetMessageBytesField(GPBMessage *self,
1289 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001290#if defined(DEBUG) && DEBUG
1291 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1292 GPBDataTypeBytes),
1293 @"Attempting to get value of NSData from field %@ "
1294 @"of %@ which is of type %@.",
1295 [self class], field.name,
1296 TypeToString(GPBGetFieldDataType(field)));
1297#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001298 return (NSData *)GPBGetObjectIvarWithField(self, field);
1299}
1300
1301// Only exists for public api, no core code should use this.
1302void GPBSetMessageBytesField(GPBMessage *self,
1303 GPBFieldDescriptor *field,
1304 NSData *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001305#if defined(DEBUG) && DEBUG
1306 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1307 GPBDataTypeBytes),
1308 @"Attempting to set field %@ of %@ which is of type %@ with "
1309 @"value of type NSData.",
1310 [self class], field.name,
1311 TypeToString(GPBGetFieldDataType(field)));
1312#endif
Thomas Van Lenten09c001e2018-10-02 10:42:55 -04001313 GPBSetCopyObjectIvarWithField(self, field, (id)value);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001314}
1315
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001316// clang-format on
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001317//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
1318// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001319// clang-format off
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001320
1321// Only exists for public api, no core code should use this.
1322GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
1323 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001324#if defined(DEBUG) && DEBUG
1325 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1326 GPBDataTypeMessage),
1327 @"Attempting to get value of GPBMessage from field %@ "
1328 @"of %@ which is of type %@.",
1329 [self class], field.name,
1330 TypeToString(GPBGetFieldDataType(field)));
1331#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001332 return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
1333}
1334
1335// Only exists for public api, no core code should use this.
1336void GPBSetMessageMessageField(GPBMessage *self,
1337 GPBFieldDescriptor *field,
1338 GPBMessage *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001339#if defined(DEBUG) && DEBUG
1340 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1341 GPBDataTypeMessage),
1342 @"Attempting to set field %@ of %@ which is of type %@ with "
1343 @"value of type GPBMessage.",
1344 [self class], field.name,
1345 TypeToString(GPBGetFieldDataType(field)));
1346#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001347 GPBSetObjectIvarWithField(self, field, (id)value);
1348}
1349
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001350// clang-format on
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001351//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
1352// This block of code is generated, do not edit it directly.
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001353// clang-format off
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001354
1355// Only exists for public api, no core code should use this.
1356GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
1357 GPBFieldDescriptor *field) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001358#if defined(DEBUG) && DEBUG
1359 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1360 GPBDataTypeGroup),
1361 @"Attempting to get value of GPBMessage from field %@ "
1362 @"of %@ which is of type %@.",
1363 [self class], field.name,
1364 TypeToString(GPBGetFieldDataType(field)));
1365#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001366 return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
1367}
1368
1369// Only exists for public api, no core code should use this.
1370void GPBSetMessageGroupField(GPBMessage *self,
1371 GPBFieldDescriptor *field,
1372 GPBMessage *value) {
dmaclach2b3aa1c2017-11-16 05:26:46 -08001373#if defined(DEBUG) && DEBUG
1374 NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field),
1375 GPBDataTypeGroup),
1376 @"Attempting to set field %@ of %@ which is of type %@ with "
1377 @"value of type GPBMessage.",
1378 [self class], field.name,
1379 TypeToString(GPBGetFieldDataType(field)));
1380#endif
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001381 GPBSetObjectIvarWithField(self, field, (id)value);
1382}
1383
Dave MacLachlanab48ecf2020-01-20 13:47:20 -08001384// clang-format on
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001385//%PDDM-EXPAND-END (4 expansions)
1386
Thomas Van Lentenfc4c6172016-06-27 20:45:16 -04001387// GPBGetMessageRepeatedField is defined in GPBMessage.m
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001388
1389// Only exists for public api, no core code should use this.
1390void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001391#if defined(DEBUG) && DEBUG
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001392 if (field.fieldType != GPBFieldTypeRepeated) {
1393 [NSException raise:NSInvalidArgumentException
1394 format:@"%@.%@ is not a repeated field.",
1395 [self class], field.name];
1396 }
1397 Class expectedClass = Nil;
1398 switch (GPBGetFieldDataType(field)) {
1399 case GPBDataTypeBool:
1400 expectedClass = [GPBBoolArray class];
1401 break;
1402 case GPBDataTypeSFixed32:
1403 case GPBDataTypeInt32:
1404 case GPBDataTypeSInt32:
1405 expectedClass = [GPBInt32Array class];
1406 break;
1407 case GPBDataTypeFixed32:
1408 case GPBDataTypeUInt32:
1409 expectedClass = [GPBUInt32Array class];
1410 break;
1411 case GPBDataTypeSFixed64:
1412 case GPBDataTypeInt64:
1413 case GPBDataTypeSInt64:
1414 expectedClass = [GPBInt64Array class];
1415 break;
1416 case GPBDataTypeFixed64:
1417 case GPBDataTypeUInt64:
1418 expectedClass = [GPBUInt64Array class];
1419 break;
1420 case GPBDataTypeFloat:
1421 expectedClass = [GPBFloatArray class];
1422 break;
1423 case GPBDataTypeDouble:
1424 expectedClass = [GPBDoubleArray class];
1425 break;
1426 case GPBDataTypeBytes:
1427 case GPBDataTypeString:
1428 case GPBDataTypeMessage:
1429 case GPBDataTypeGroup:
Jon Walle72805e2016-05-26 12:23:41 -04001430 expectedClass = [NSMutableArray class];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001431 break;
1432 case GPBDataTypeEnum:
Jon Walle72805e2016-05-26 12:23:41 -04001433 expectedClass = [GPBEnumArray class];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001434 break;
1435 }
1436 if (array && ![array isKindOfClass:expectedClass]) {
1437 [NSException raise:NSInvalidArgumentException
1438 format:@"%@.%@: Expected %@ object, got %@.",
1439 [self class], field.name, expectedClass, [array class]];
1440 }
1441#endif
1442 GPBSetObjectIvarWithField(self, field, array);
1443}
1444
dmaclach2b3aa1c2017-11-16 05:26:46 -08001445static GPBDataType BaseDataType(GPBDataType type) {
1446 switch (type) {
1447 case GPBDataTypeSFixed32:
1448 case GPBDataTypeInt32:
1449 case GPBDataTypeSInt32:
1450 case GPBDataTypeEnum:
1451 return GPBDataTypeInt32;
1452 case GPBDataTypeFixed32:
1453 case GPBDataTypeUInt32:
1454 return GPBDataTypeUInt32;
1455 case GPBDataTypeSFixed64:
1456 case GPBDataTypeInt64:
1457 case GPBDataTypeSInt64:
1458 return GPBDataTypeInt64;
1459 case GPBDataTypeFixed64:
1460 case GPBDataTypeUInt64:
1461 return GPBDataTypeUInt64;
1462 case GPBDataTypeMessage:
1463 case GPBDataTypeGroup:
1464 return GPBDataTypeMessage;
1465 case GPBDataTypeBool:
1466 case GPBDataTypeFloat:
1467 case GPBDataTypeDouble:
1468 case GPBDataTypeBytes:
1469 case GPBDataTypeString:
1470 return type;
1471 }
1472}
1473
1474static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) {
1475 return BaseDataType(type1) == BaseDataType(type2);
1476}
1477
1478static NSString *TypeToString(GPBDataType dataType) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001479 switch (dataType) {
1480 case GPBDataTypeBool:
1481 return @"Bool";
1482 case GPBDataTypeSFixed32:
1483 case GPBDataTypeInt32:
1484 case GPBDataTypeSInt32:
1485 return @"Int32";
1486 case GPBDataTypeFixed32:
1487 case GPBDataTypeUInt32:
1488 return @"UInt32";
1489 case GPBDataTypeSFixed64:
1490 case GPBDataTypeInt64:
1491 case GPBDataTypeSInt64:
1492 return @"Int64";
1493 case GPBDataTypeFixed64:
1494 case GPBDataTypeUInt64:
1495 return @"UInt64";
1496 case GPBDataTypeFloat:
1497 return @"Float";
1498 case GPBDataTypeDouble:
1499 return @"Double";
1500 case GPBDataTypeBytes:
1501 case GPBDataTypeString:
1502 case GPBDataTypeMessage:
1503 case GPBDataTypeGroup:
1504 return @"Object";
1505 case GPBDataTypeEnum:
dmaclach2b3aa1c2017-11-16 05:26:46 -08001506 return @"Enum";
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001507 }
1508}
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001509
Thomas Van Lentenfc4c6172016-06-27 20:45:16 -04001510// GPBGetMessageMapField is defined in GPBMessage.m
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001511
1512// Only exists for public api, no core code should use this.
1513void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
1514 id dictionary) {
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001515#if defined(DEBUG) && DEBUG
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001516 if (field.fieldType != GPBFieldTypeMap) {
1517 [NSException raise:NSInvalidArgumentException
1518 format:@"%@.%@ is not a map<> field.",
1519 [self class], field.name];
1520 }
1521 if (dictionary) {
1522 GPBDataType keyDataType = field.mapKeyDataType;
1523 GPBDataType valueDataType = GPBGetFieldDataType(field);
dmaclach2b3aa1c2017-11-16 05:26:46 -08001524 NSString *keyStr = TypeToString(keyDataType);
1525 NSString *valueStr = TypeToString(valueDataType);
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001526 if (keyDataType == GPBDataTypeString) {
1527 keyStr = @"String";
1528 }
1529 Class expectedClass = Nil;
1530 if ((keyDataType == GPBDataTypeString) &&
1531 GPBDataTypeIsObject(valueDataType)) {
1532 expectedClass = [NSMutableDictionary class];
1533 } else {
1534 NSString *className =
1535 [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
1536 expectedClass = NSClassFromString(className);
1537 NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
1538 }
1539 if (![dictionary isKindOfClass:expectedClass]) {
1540 [NSException raise:NSInvalidArgumentException
1541 format:@"%@.%@: Expected %@ object, got %@.",
1542 [self class], field.name, expectedClass,
1543 [dictionary class]];
1544 }
1545 }
1546#endif
1547 GPBSetObjectIvarWithField(self, field, dictionary);
1548}
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001549
1550#pragma mark - Misc Dynamic Runtime Utils
1551
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001552const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
1553 Protocol *protocol =
1554 objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
Dave MacLachlan37a66722017-11-14 15:16:04 -08001555 NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol");
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001556 struct objc_method_description description =
1557 protocol_getMethodDescription(protocol, selector, NO, instanceSel);
Dave MacLachlan37a66722017-11-14 15:16:04 -08001558 NSCAssert(description.name != Nil && description.types != nil,
1559 @"Missing method for selector %@", NSStringFromSelector(selector));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001560 return description.types;
1561}
1562
1563#pragma mark - Text Format Support
1564
1565static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
1566 [destStr appendString:@"\""];
1567 NSUInteger len = [toPrint length];
1568 for (NSUInteger i = 0; i < len; ++i) {
1569 unichar aChar = [toPrint characterAtIndex:i];
1570 switch (aChar) {
1571 case '\n': [destStr appendString:@"\\n"]; break;
1572 case '\r': [destStr appendString:@"\\r"]; break;
1573 case '\t': [destStr appendString:@"\\t"]; break;
1574 case '\"': [destStr appendString:@"\\\""]; break;
1575 case '\'': [destStr appendString:@"\\\'"]; break;
1576 case '\\': [destStr appendString:@"\\\\"]; break;
1577 default:
Thomas Van Lenten1a6c1d02016-08-08 18:02:43 -04001578 // This differs slightly from the C++ code in that the C++ doesn't
1579 // generate UTF8; it looks at the string in UTF8, but escapes every
1580 // byte > 0x7E.
1581 if (aChar < 0x20) {
1582 [destStr appendFormat:@"\\%d%d%d",
1583 (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
1584 } else {
1585 [destStr appendFormat:@"%C", aChar];
1586 }
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001587 break;
1588 }
1589 }
1590 [destStr appendString:@"\""];
1591}
1592
1593static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
1594 const char *src = (const char *)[buffer bytes];
1595 size_t srcLen = [buffer length];
1596 [destStr appendString:@"\""];
1597 for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
1598 switch (*src) {
1599 case '\n': [destStr appendString:@"\\n"]; break;
1600 case '\r': [destStr appendString:@"\\r"]; break;
1601 case '\t': [destStr appendString:@"\\t"]; break;
1602 case '\"': [destStr appendString:@"\\\""]; break;
1603 case '\'': [destStr appendString:@"\\\'"]; break;
1604 case '\\': [destStr appendString:@"\\\\"]; break;
1605 default:
1606 if (isprint(*src)) {
1607 [destStr appendFormat:@"%c", *src];
1608 } else {
1609 // NOTE: doing hex means you have to worry about the letter after
1610 // the hex being another hex char and forcing that to be escaped, so
1611 // use octal to keep it simple.
1612 [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
1613 }
1614 break;
1615 }
1616 }
1617 [destStr appendString:@"\""];
1618}
1619
1620static void AppendTextFormatForMapMessageField(
1621 id map, GPBFieldDescriptor *field, NSMutableString *toStr,
1622 NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001623 GPBDataType keyDataType = field.mapKeyDataType;
1624 GPBDataType valueDataType = GPBGetFieldDataType(field);
1625 BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001626
1627 NSString *msgStartFirst =
1628 [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
1629 NSString *msgStart =
1630 [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
1631 NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
1632
1633 NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent];
1634 NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent,
1635 (isMessageValue ? "" : ":")];
1636
1637 __block BOOL isFirst = YES;
1638
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001639 if ((keyDataType == GPBDataTypeString) &&
1640 GPBDataTypeIsObject(valueDataType)) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001641 // map is an NSDictionary.
1642 NSDictionary *dict = map;
1643 [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
1644 #pragma unused(stop)
1645 [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
1646 isFirst = NO;
1647
1648 [toStr appendString:keyLine];
1649 AppendStringEscaped(key, toStr);
1650 [toStr appendString:@"\n"];
1651
1652 [toStr appendString:valueLine];
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001653#pragma clang diagnostic push
1654#pragma clang diagnostic ignored "-Wswitch-enum"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001655 switch (valueDataType) {
1656 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001657 AppendStringEscaped(value, toStr);
1658 break;
1659
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001660 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001661 AppendBufferAsString(value, toStr);
1662 break;
1663
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001664 case GPBDataTypeMessage:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001665 [toStr appendString:@"{\n"];
1666 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1667 AppendTextFormatForMessage(value, toStr, subIndent);
1668 [toStr appendFormat:@"%@ }", lineIndent];
1669 break;
1670
1671 default:
1672 NSCAssert(NO, @"Can't happen");
1673 break;
1674 }
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001675#pragma clang diagnostic pop
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001676 [toStr appendString:@"\n"];
1677
1678 [toStr appendString:msgEnd];
1679 }];
1680 } else {
1681 // map is one of the GPB*Dictionary classes, type doesn't matter.
1682 GPBInt32Int32Dictionary *dict = map;
1683 [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
1684 [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
1685 isFirst = NO;
1686
1687 // Key always is a NSString.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001688 if (keyDataType == GPBDataTypeString) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001689 [toStr appendString:keyLine];
1690 AppendStringEscaped(keyObj, toStr);
1691 [toStr appendString:@"\n"];
1692 } else {
1693 [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
1694 }
1695
1696 [toStr appendString:valueLine];
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001697#pragma clang diagnostic push
1698#pragma clang diagnostic ignored "-Wswitch-enum"
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001699 switch (valueDataType) {
1700 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001701 AppendStringEscaped(valueObj, toStr);
1702 break;
1703
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001704 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001705 AppendBufferAsString(valueObj, toStr);
1706 break;
1707
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001708 case GPBDataTypeMessage:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001709 [toStr appendString:@"{\n"];
1710 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1711 AppendTextFormatForMessage(valueObj, toStr, subIndent);
1712 [toStr appendFormat:@"%@ }", lineIndent];
1713 break;
1714
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001715 case GPBDataTypeEnum: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001716 int32_t enumValue = [valueObj intValue];
1717 NSString *valueStr = nil;
1718 GPBEnumDescriptor *descriptor = field.enumDescriptor;
1719 if (descriptor) {
1720 valueStr = [descriptor textFormatNameForValue:enumValue];
1721 }
1722 if (valueStr) {
1723 [toStr appendString:valueStr];
1724 } else {
1725 [toStr appendFormat:@"%d", enumValue];
1726 }
1727 break;
1728 }
1729
1730 default:
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001731 NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001732 // Everything else is a NSString.
1733 [toStr appendString:valueObj];
1734 break;
1735 }
Thomas Van Lentenc8a440d2016-05-25 13:46:00 -04001736#pragma clang diagnostic pop
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001737 [toStr appendString:@"\n"];
1738
1739 [toStr appendString:msgEnd];
1740 }];
1741 }
1742}
1743
1744static void AppendTextFormatForMessageField(GPBMessage *message,
1745 GPBFieldDescriptor *field,
1746 NSMutableString *toStr,
1747 NSString *lineIndent) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001748 id arrayOrMap;
1749 NSUInteger count;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001750 GPBFieldType fieldType = field.fieldType;
1751 switch (fieldType) {
1752 case GPBFieldTypeSingle:
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001753 arrayOrMap = nil;
1754 count = (GPBGetHasIvarField(message, field) ? 1 : 0);
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001755 break;
1756
1757 case GPBFieldTypeRepeated:
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001758 // Will be NSArray or GPB*Array, type doesn't matter, they both
1759 // implement count.
1760 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
1761 count = [(NSArray *)arrayOrMap count];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001762 break;
1763
1764 case GPBFieldTypeMap: {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001765 // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter,
1766 // they both implement count.
1767 arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
1768 count = [(NSDictionary *)arrayOrMap count];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001769 break;
1770 }
1771 }
1772
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001773 if (count == 0) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001774 // Nothing to print, out of here.
1775 return;
1776 }
1777
1778 NSString *lineEnding = @"";
1779
1780 // If the name can't be reversed or support for extra info was turned off,
1781 // this can return nil.
1782 NSString *fieldName = [field textFormatName];
1783 if ([fieldName length] == 0) {
1784 fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
1785 // If there is only one entry, put the objc name as a comment, other wise
Dongjoon Hyun7a9040f2016-01-14 22:12:03 -08001786 // add it before the repeated values.
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001787 if (count > 1) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001788 [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
1789 } else {
1790 lineEnding = [NSString stringWithFormat:@" # %@", field.name];
1791 }
1792 }
1793
1794 if (fieldType == GPBFieldTypeMap) {
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001795 AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent,
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001796 fieldName, lineEnding);
1797 return;
1798 }
1799
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001800 id array = arrayOrMap;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001801 const BOOL isRepeated = (array != nil);
1802
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001803 GPBDataType fieldDataType = GPBGetFieldDataType(field);
1804 BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001805 for (NSUInteger j = 0; j < count; ++j) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001806 // Start the line.
1807 [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
1808 (isMessageField ? "" : ":")];
1809
1810 // The value.
1811 switch (fieldDataType) {
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001812#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \
1813 case GPBDataType##GPBDATATYPE: { \
1814 CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \
1815 : GPBGetMessage##REAL_TYPE##Field(message, field)); \
1816 [toStr appendFormat:__VA_ARGS__, v]; \
1817 break; \
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001818 }
1819
1820 FIELD_CASE(Int32, int32_t, Int32, @"%d")
1821 FIELD_CASE(SInt32, int32_t, Int32, @"%d")
1822 FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
1823 FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
1824 FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
1825 FIELD_CASE(Int64, int64_t, Int64, @"%lld")
1826 FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
1827 FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
1828 FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
1829 FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
1830 FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
1831 FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
1832
1833#undef FIELD_CASE
1834
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001835 case GPBDataTypeEnum: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001836 int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001837 : GPBGetMessageInt32Field(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001838 NSString *valueStr = nil;
1839 GPBEnumDescriptor *descriptor = field.enumDescriptor;
1840 if (descriptor) {
1841 valueStr = [descriptor textFormatNameForValue:v];
1842 }
1843 if (valueStr) {
1844 [toStr appendString:valueStr];
1845 } else {
1846 [toStr appendFormat:@"%d", v];
1847 }
1848 break;
1849 }
1850
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001851 case GPBDataTypeBool: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001852 BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001853 : GPBGetMessageBoolField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001854 [toStr appendString:(v ? @"true" : @"false")];
1855 break;
1856 }
1857
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001858 case GPBDataTypeString: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001859 NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001860 : GPBGetMessageStringField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001861 AppendStringEscaped(v, toStr);
1862 break;
1863 }
1864
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001865 case GPBDataTypeBytes: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001866 NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001867 : GPBGetMessageBytesField(message, field));
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001868 AppendBufferAsString(v, toStr);
1869 break;
1870 }
1871
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001872 case GPBDataTypeGroup:
1873 case GPBDataTypeMessage: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001874 GPBMessage *v =
1875 (isRepeated ? [(NSArray *)array objectAtIndex:j]
1876 : GPBGetObjectIvarWithField(message, field));
1877 [toStr appendFormat:@"{%@\n", lineEnding];
1878 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1879 AppendTextFormatForMessage(v, toStr, subIndent);
1880 [toStr appendFormat:@"%@}", lineIndent];
1881 lineEnding = @"";
1882 break;
1883 }
1884
1885 } // switch(fieldDataType)
1886
1887 // End the line.
1888 [toStr appendFormat:@"%@\n", lineEnding];
1889
Thomas Van Lenten1dcc3292015-05-21 17:14:52 -04001890 } // for(count)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001891}
1892
1893static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
1894 NSArray *activeExtensions,
1895 GPBExtensionRange range,
1896 NSMutableString *toStr,
1897 NSString *lineIndent) {
1898 uint32_t start = range.start;
1899 uint32_t end = range.end;
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001900 for (GPBExtensionDescriptor *extension in activeExtensions) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001901 uint32_t fieldNumber = extension.fieldNumber;
1902 if (fieldNumber < start) {
1903 // Not there yet.
1904 continue;
1905 }
Thomas Van Lentenaf2d4132018-11-14 16:09:43 -05001906 if (fieldNumber >= end) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001907 // Done.
1908 break;
1909 }
1910
1911 id rawExtValue = [message getExtension:extension];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001912 BOOL isRepeated = extension.isRepeated;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001913
1914 NSUInteger numValues = 1;
1915 NSString *lineEnding = @"";
1916 if (isRepeated) {
1917 numValues = [(NSArray *)rawExtValue count];
1918 }
1919
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001920 NSString *singletonName = extension.singletonName;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001921 if (numValues == 1) {
1922 lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName];
1923 } else {
1924 [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
1925 }
1926
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001927 GPBDataType extDataType = extension.dataType;
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001928 for (NSUInteger j = 0; j < numValues; ++j) {
1929 id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
1930
1931 // Start the line.
1932 [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001933 (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001934
1935 // The value.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001936 switch (extDataType) {
1937#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
1938 case GPBDataType##GPBDATATYPE: { \
1939 CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \
1940 [toStr appendFormat:__VA_ARGS__, v]; \
1941 break; \
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001942 }
1943
1944 FIELD_CASE(Int32, int32_t, intValue, @"%d")
1945 FIELD_CASE(SInt32, int32_t, intValue, @"%d")
1946 FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
1947 FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
1948 FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
1949 FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
1950 FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
1951 FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
1952 FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
1953 FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
1954 FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
1955 FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
1956 // TODO: Add a comment with the enum name from enum descriptors
1957 // (might not be real value, so leave it as a comment, ObjC compiler
1958 // name mangles differently). Doesn't look like we actually generate
1959 // an enum descriptor reference like we do for normal fields, so this
1960 // will take a compiler change.
1961 FIELD_CASE(Enum, int32_t, intValue, @"%d")
1962
1963#undef FIELD_CASE
1964
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001965 case GPBDataTypeBool:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001966 [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
1967 : @"false")];
1968 break;
1969
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001970 case GPBDataTypeString:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001971 AppendStringEscaped(curValue, toStr);
1972 break;
1973
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001974 case GPBDataTypeBytes:
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001975 AppendBufferAsString((NSData *)curValue, toStr);
1976 break;
1977
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001978 case GPBDataTypeGroup:
1979 case GPBDataTypeMessage: {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001980 [toStr appendFormat:@"{%@\n", lineEnding];
1981 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
1982 AppendTextFormatForMessage(curValue, toStr, subIndent);
1983 [toStr appendFormat:@"%@}", lineIndent];
1984 lineEnding = @"";
1985 break;
1986 }
1987
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04001988 } // switch(extDataType)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001989
Thomas Van Lenten3eb28892018-11-14 15:20:13 -05001990 // End the line.
1991 [toStr appendFormat:@"%@\n", lineEnding];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001992
Thomas Van Lenten3eb28892018-11-14 15:20:13 -05001993 } // for(numValues)
Thomas Van Lenten30650d82015-05-01 08:57:16 -04001994
1995 } // for..in(activeExtensions)
1996}
1997
1998static void AppendTextFormatForMessage(GPBMessage *message,
1999 NSMutableString *toStr,
2000 NSString *lineIndent) {
2001 GPBDescriptor *descriptor = [message descriptor];
2002 NSArray *fieldsArray = descriptor->fields_;
2003 NSUInteger fieldCount = fieldsArray.count;
2004 const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
2005 NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
Sergio Campamáb99577c2016-07-15 15:04:01 -07002006 NSArray *activeExtensions = [[message extensionsCurrentlySet]
2007 sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002008 for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
2009 if (i == fieldCount) {
2010 AppendTextFormatForMessageExtensionRange(
2011 message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
2012 } else if (j == extensionRangesCount ||
2013 GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
2014 AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
2015 lineIndent);
2016 } else {
2017 AppendTextFormatForMessageExtensionRange(
2018 message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
2019 }
2020 }
2021
2022 NSString *unknownFieldsStr =
2023 GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
2024 if ([unknownFieldsStr length] > 0) {
2025 [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
2026 [toStr appendString:unknownFieldsStr];
2027 }
2028}
2029
2030NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
Thomas Van Lenten8c889572015-06-16 16:45:14 -04002031 if (message == nil) return @"";
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002032 if (lineIndent == nil) lineIndent = @"";
2033
2034 NSMutableString *buildString = [NSMutableString string];
2035 AppendTextFormatForMessage(message, buildString, lineIndent);
2036 return buildString;
2037}
2038
2039NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
2040 NSString *lineIndent) {
Thomas Van Lenten8c889572015-06-16 16:45:14 -04002041 if (unknownSet == nil) return @"";
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002042 if (lineIndent == nil) lineIndent = @"";
2043
2044 NSMutableString *result = [NSMutableString string];
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04002045 for (GPBUnknownField *field in [unknownSet sortedFields]) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002046 int32_t fieldNumber = [field number];
2047
2048#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \
2049 [field.PROPNAME \
2050 enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \
2051 _Pragma("unused(idx, stop)"); \
2052 [result \
2053 appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
2054 }];
2055
2056 PRINT_LOOP(varintList, uint64_t, %llu);
2057 PRINT_LOOP(fixed32List, uint32_t, 0x%X);
2058 PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
2059
2060#undef PRINT_LOOP
2061
2062 // NOTE: C++ version of TextFormat tries to parse this as a message
2063 // and print that if it succeeds.
2064 for (NSData *data in field.lengthDelimitedList) {
2065 [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
2066 AppendBufferAsString(data, result);
2067 [result appendString:@"\n"];
2068 }
2069
2070 for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
2071 [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
2072 NSString *subIndent = [lineIndent stringByAppendingString:@" "];
Tamarous6718fa92022-04-27 00:25:01 +08002073 NSString *subUnknownSetStr =
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002074 GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
Tamarous6718fa92022-04-27 00:25:01 +08002075 [result appendString:subUnknownSetStr];
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002076 [result appendFormat:@"%@}\n", lineIndent];
2077 }
2078 }
2079 return result;
2080}
2081
2082// Helpers to decode a varint. Not using GPBCodedInputStream version because
2083// that needs a state object, and we don't want to create an input stream out
2084// of the data.
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04002085GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002086 int8_t result = *((int8_t *)(*data));
2087 ++(*data);
2088 return result;
2089}
2090
Thomas Van Lentend846b0b2015-06-08 16:24:57 -04002091static int32_t ReadRawVarint32FromData(const uint8_t **data) {
Thomas Van Lenten30650d82015-05-01 08:57:16 -04002092 int8_t tmp = ReadRawByteFromData(data);
2093 if (tmp >= 0) {
2094 return tmp;
2095 }
2096 int32_t result = tmp & 0x7f;
2097 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2098 result |= tmp << 7;
2099 } else {
2100 result |= (tmp & 0x7f) << 7;
2101 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2102 result |= tmp << 14;
2103 } else {
2104 result |= (tmp & 0x7f) << 14;
2105 if ((tmp = ReadRawByteFromData(data)) >= 0) {
2106 result |= tmp << 21;
2107 } else {
2108 result |= (tmp & 0x7f) << 21;
2109 result |= (tmp = ReadRawByteFromData(data)) << 28;
2110 if (tmp < 0) {
2111 // Discard upper 32 bits.
2112 for (int i = 0; i < 5; i++) {
2113 if (ReadRawByteFromData(data) >= 0) {
2114 return result;
2115 }
2116 }
2117 [NSException raise:NSParseErrorException
2118 format:@"Unable to read varint32"];
2119 }
2120 }
2121 }
2122 }
2123 return result;
2124}
2125
2126NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
2127 NSString *inputStr) {
2128 // decodData form:
2129 // varint32: num entries
2130 // for each entry:
2131 // varint32: key
2132 // bytes*: decode data
2133 //
2134 // decode data one of two forms:
2135 // 1: a \0 followed by the string followed by an \0
2136 // 2: bytecodes to transform an input into the right thing, ending with \0
2137 //
2138 // the bytes codes are of the form:
2139 // 0xabbccccc
2140 // 0x0 (all zeros), end.
2141 // a - if set, add an underscore
2142 // bb - 00 ccccc bytes as is
2143 // bb - 10 ccccc upper first, as is on rest, ccccc byte total
2144 // bb - 01 ccccc lower first, as is on rest, ccccc byte total
2145 // bb - 11 ccccc all upper, ccccc byte total
2146
2147 if (!decodeData || !inputStr) {
2148 return nil;
2149 }
2150
2151 // Find key
2152 const uint8_t *scan = decodeData;
2153 int32_t numEntries = ReadRawVarint32FromData(&scan);
2154 BOOL foundKey = NO;
2155 while (!foundKey && (numEntries > 0)) {
2156 --numEntries;
2157 int32_t dataKey = ReadRawVarint32FromData(&scan);
2158 if (dataKey == key) {
2159 foundKey = YES;
2160 } else {
2161 // If it is a inlined string, it will start with \0; if it is bytecode it
2162 // will start with a code. So advance one (skipping the inline string
2163 // marker), and then loop until reaching the end marker (\0).
2164 ++scan;
2165 while (*scan != 0) ++scan;
2166 // Now move past the end marker.
2167 ++scan;
2168 }
2169 }
2170
2171 if (!foundKey) {
2172 return nil;
2173 }
2174
2175 // Decode
2176
2177 if (*scan == 0) {
2178 // Inline string. Move over the marker, and NSString can take it as
2179 // UTF8.
2180 ++scan;
2181 NSString *result = [NSString stringWithUTF8String:(const char *)scan];
2182 return result;
2183 }
2184
2185 NSMutableString *result =
2186 [NSMutableString stringWithCapacity:[inputStr length]];
2187
2188 const uint8_t kAddUnderscore = 0b10000000;
2189 const uint8_t kOpMask = 0b01100000;
2190 // const uint8_t kOpAsIs = 0b00000000;
2191 const uint8_t kOpFirstUpper = 0b01000000;
2192 const uint8_t kOpFirstLower = 0b00100000;
2193 const uint8_t kOpAllUpper = 0b01100000;
2194 const uint8_t kSegmentLenMask = 0b00011111;
2195
2196 NSInteger i = 0;
2197 for (; *scan != 0; ++scan) {
2198 if (*scan & kAddUnderscore) {
2199 [result appendString:@"_"];
2200 }
2201 int segmentLen = *scan & kSegmentLenMask;
2202 uint8_t decodeOp = *scan & kOpMask;
2203
2204 // Do op specific handling of the first character.
2205 if (decodeOp == kOpFirstUpper) {
2206 unichar c = [inputStr characterAtIndex:i];
2207 [result appendFormat:@"%c", toupper((char)c)];
2208 ++i;
2209 --segmentLen;
2210 } else if (decodeOp == kOpFirstLower) {
2211 unichar c = [inputStr characterAtIndex:i];
2212 [result appendFormat:@"%c", tolower((char)c)];
2213 ++i;
2214 --segmentLen;
2215 }
2216 // else op == kOpAsIs || op == kOpAllUpper
2217
2218 // Now pull over the rest of the length for this segment.
2219 for (int x = 0; x < segmentLen; ++x) {
2220 unichar c = [inputStr characterAtIndex:(i + x)];
2221 if (decodeOp == kOpAllUpper) {
2222 [result appendFormat:@"%c", toupper((char)c)];
2223 } else {
2224 [result appendFormat:@"%C", c];
2225 }
2226 }
2227 i += segmentLen;
2228 }
2229
2230 return result;
2231}
2232
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04002233#pragma mark Legacy methods old generated code calls
2234
2235// Shim from the older generated code into the runtime.
2236void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
2237 GPBFieldDescriptor *field,
2238 int32_t value,
2239 GPBFileSyntax syntax) {
2240#pragma unused(syntax)
2241 GPBSetMessageInt32Field(self, field, value);
2242}
2243
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04002244void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
2245 int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
2246#pragma unused(fieldNumberNotToClear)
2247 #if defined(DEBUG) && DEBUG
2248 NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof,
2249 @"OneofDescriptor %@ doesn't appear to be for %@ messages.",
2250 oneof.name, [self class]);
Vy Nguyen60a7f1f2022-06-22 15:19:21 -04002251 GPBFieldDescriptor *firstField __unused = oneof->fields_[0];
Thomas Van Lenten3c8e9592020-04-13 10:49:16 -04002252 NSCAssert(firstField->description_->hasIndex == oneofHasIndex,
2253 @"Internal error, oneofHasIndex (%d) doesn't match (%d).",
2254 firstField->description_->hasIndex, oneofHasIndex);
2255 #endif
2256 GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0);
2257}
2258
2259#pragma clang diagnostic pop
2260
Thomas Van Lentene1e5b8a2020-04-10 15:55:32 -04002261#pragma mark Misc Helpers
2262
Thomas Van Lenten2d1c5e22017-03-02 14:50:10 -05002263BOOL GPBClassHasSel(Class aClass, SEL sel) {
2264 // NOTE: We have to use class_copyMethodList, all other runtime method
2265 // lookups actually also resolve the method implementation and this
2266 // is called from within those methods.
2267
2268 BOOL result = NO;
2269 unsigned int methodCount = 0;
2270 Method *methodList = class_copyMethodList(aClass, &methodCount);
2271 for (unsigned int i = 0; i < methodCount; ++i) {
2272 SEL methodSelector = method_getName(methodList[i]);
2273 if (methodSelector == sel) {
2274 result = YES;
2275 break;
2276 }
2277 }
2278 free(methodList);
2279 return result;
2280}