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