| Index: third_party/protobuf/objectivec/GPBUtilities.m
|
| diff --git a/third_party/protobuf/objectivec/GPBUtilities.m b/third_party/protobuf/objectivec/GPBUtilities.m
|
| index 447c749aa76779877e6f754a69f248ba414cf1db..d4538598f72c61fa2153feed1099017ac6a4db5d 100644
|
| --- a/third_party/protobuf/objectivec/GPBUtilities.m
|
| +++ b/third_party/protobuf/objectivec/GPBUtilities.m
|
| @@ -39,6 +39,12 @@
|
| #import "GPBUnknownField.h"
|
| #import "GPBUnknownFieldSet.h"
|
|
|
| +// Direct access is use for speed, to avoid even internally declaring things
|
| +// read/write, etc. The warning is enabled in the project to ensure code calling
|
| +// protos can turn on -Wdirect-ivar-access without issues.
|
| +#pragma clang diagnostic push
|
| +#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
| +
|
| static void AppendTextFormatForMessage(GPBMessage *message,
|
| NSMutableString *toStr,
|
| NSString *lineIndent);
|
| @@ -52,8 +58,50 @@ NSData *GPBEmptyNSData(void) {
|
| return defaultNSData;
|
| }
|
|
|
| +// -- About Version Checks --
|
| +// There's actually 3 places these checks all come into play:
|
| +// 1. When the generated source is compile into .o files, the header check
|
| +// happens. This is checking the protoc used matches the library being used
|
| +// when making the .o.
|
| +// 2. Every place a generated proto header is included in a developer's code,
|
| +// the header check comes into play again. But this time it is checking that
|
| +// the current library headers being used still support/match the ones for
|
| +// the generated code.
|
| +// 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is
|
| +// called from the generated code passing in values captured when the
|
| +// generated code's .o was made. This checks that at runtime the generated
|
| +// code and runtime library match.
|
| +
|
| +void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) {
|
| + // NOTE: This is passing the value captured in the compiled code to check
|
| + // against the values captured when the runtime support was compiled. This
|
| + // ensures the library code isn't in a different framework/library that
|
| + // was generated with a non matching version.
|
| + if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) {
|
| + // Library is too old for headers.
|
| + [NSException raise:NSInternalInconsistencyException
|
| + format:@"Linked to ProtocolBuffer runtime version %d,"
|
| + @" but code compiled needing atleast %d!",
|
| + GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
|
| + }
|
| + if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
|
| + // Headers are too old for library.
|
| + [NSException raise:NSInternalInconsistencyException
|
| + format:@"Proto generation source compiled against runtime"
|
| + @" version %d, but this version of the runtime only"
|
| + @" supports back to %d!",
|
| + objcRuntimeVersion,
|
| + GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
|
| + }
|
| +}
|
| +
|
| +// This api is no longer used for version checks. 30001 is the last version
|
| +// using this old versioning model. When that support is removed, this function
|
| +// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h).
|
| void GPBCheckRuntimeVersionInternal(int32_t version) {
|
| - if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) {
|
| + GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001,
|
| + time_to_remove_this_old_version_shim);
|
| + if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
|
| [NSException raise:NSInternalInconsistencyException
|
| format:@"Linked to ProtocolBuffer runtime version %d,"
|
| @" but code compiled with version %d!",
|
| @@ -212,9 +260,10 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
|
| //% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
|
| //% *typePtr = value;
|
| //% // proto2: any value counts as having been set; proto3, it
|
| -//% // has to be a non zero value.
|
| -//% BOOL hasValue =
|
| -//% (syntax == GPBFileSyntaxProto2) || (value != (TYPE)0);
|
| +//% // has to be a non zero value or be in a oneof.
|
| +//% BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| +//% || (value != (TYPE)0)
|
| +//% || (field->containingOneof_ != NULL));
|
| //% GPBSetHasIvarField(self, field, hasValue);
|
| //% GPBBecomeVisibleToAutocreator(self);
|
| //%}
|
| @@ -331,8 +380,19 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
|
| // zero, they are being cleared.
|
| if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
|
| ([value length] == 0)) {
|
| - setHasValue = NO;
|
| - value = nil;
|
| + // Except, if the field was in a oneof, then it still gets recorded as
|
| + // having been set so the state of the oneof can be serialized back out.
|
| + if (!oneof) {
|
| + setHasValue = NO;
|
| + }
|
| + if (setHasValue) {
|
| + NSCAssert(value != nil, @"Should never be setting has for nil");
|
| + } else {
|
| + // The value passed in was retained, it must be released since we
|
| + // aren't saving anything in the field.
|
| + [value release];
|
| + value = nil;
|
| + }
|
| }
|
| GPBSetHasIvarField(self, field, setHasValue);
|
| }
|
| @@ -518,9 +578,10 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
|
| GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
|
|
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (BOOL)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (BOOL)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -567,9 +628,10 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
|
| int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (int32_t)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (int32_t)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -616,9 +678,10 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
|
| uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (uint32_t)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -665,9 +728,10 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
|
| int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (int64_t)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (int64_t)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -714,9 +778,10 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
|
| uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (uint64_t)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -763,9 +828,10 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
|
| float *typePtr = (float *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (float)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (float)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -812,9 +878,10 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
|
| double *typePtr = (double *)&storage[field->description_->offset];
|
| *typePtr = value;
|
| // proto2: any value counts as having been set; proto3, it
|
| - // has to be a non zero value.
|
| - BOOL hasValue =
|
| - (syntax == GPBFileSyntaxProto2) || (value != (double)0);
|
| + // has to be a non zero value or be in a oneof.
|
| + BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
|
| + || (value != (double)0)
|
| + || (field->containingOneof_ != NULL));
|
| GPBSetHasIvarField(self, field, hasValue);
|
| GPBBecomeVisibleToAutocreator(self);
|
| }
|
| @@ -889,21 +956,11 @@ void GPBSetMessageGroupField(GPBMessage *self,
|
|
|
| //%PDDM-EXPAND-END (4 expansions)
|
|
|
| -// Only exists for public api, no core code should use this.
|
| -id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) {
|
| -#if DEBUG
|
| - if (field.fieldType != GPBFieldTypeRepeated) {
|
| - [NSException raise:NSInvalidArgumentException
|
| - format:@"%@.%@ is not a repeated field.",
|
| - [self class], field.name];
|
| - }
|
| -#endif
|
| - return GPBGetObjectIvarWithField(self, field);
|
| -}
|
| +// GPBGetMessageRepeatedField is defined in GPBMessage.m
|
|
|
| // Only exists for public api, no core code should use this.
|
| void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
|
| -#if DEBUG
|
| +#if defined(DEBUG) && DEBUG
|
| if (field.fieldType != GPBFieldTypeRepeated) {
|
| [NSException raise:NSInvalidArgumentException
|
| format:@"%@.%@ is not a repeated field.",
|
| @@ -942,10 +999,10 @@ void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id
|
| case GPBDataTypeString:
|
| case GPBDataTypeMessage:
|
| case GPBDataTypeGroup:
|
| - expectedClass = [NSMutableDictionary class];
|
| + expectedClass = [NSMutableArray class];
|
| break;
|
| case GPBDataTypeEnum:
|
| - expectedClass = [GPBBoolArray class];
|
| + expectedClass = [GPBEnumArray class];
|
| break;
|
| }
|
| if (array && ![array isKindOfClass:expectedClass]) {
|
| @@ -957,7 +1014,7 @@ void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id
|
| GPBSetObjectIvarWithField(self, field, array);
|
| }
|
|
|
| -#if DEBUG
|
| +#if defined(DEBUG) && DEBUG
|
| static NSString *TypeToStr(GPBDataType dataType) {
|
| switch (dataType) {
|
| case GPBDataTypeBool:
|
| @@ -991,22 +1048,12 @@ static NSString *TypeToStr(GPBDataType dataType) {
|
| }
|
| #endif
|
|
|
| -// Only exists for public api, no core code should use this.
|
| -id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) {
|
| -#if DEBUG
|
| - if (field.fieldType != GPBFieldTypeMap) {
|
| - [NSException raise:NSInvalidArgumentException
|
| - format:@"%@.%@ is not a map<> field.",
|
| - [self class], field.name];
|
| - }
|
| -#endif
|
| - return GPBGetObjectIvarWithField(self, field);
|
| -}
|
| +// GPBGetMessageMapField is defined in GPBMessage.m
|
|
|
| // Only exists for public api, no core code should use this.
|
| void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
|
| id dictionary) {
|
| -#if DEBUG
|
| +#if defined(DEBUG) && DEBUG
|
| if (field.fieldType != GPBFieldTypeMap) {
|
| [NSException raise:NSInvalidArgumentException
|
| format:@"%@.%@ is not a map<> field.",
|
| @@ -1066,7 +1113,15 @@ static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
|
| case '\'': [destStr appendString:@"\\\'"]; break;
|
| case '\\': [destStr appendString:@"\\\\"]; break;
|
| default:
|
| - [destStr appendFormat:@"%C", aChar];
|
| + // This differs slightly from the C++ code in that the C++ doesn't
|
| + // generate UTF8; it looks at the string in UTF8, but escapes every
|
| + // byte > 0x7E.
|
| + if (aChar < 0x20) {
|
| + [destStr appendFormat:@"\\%d%d%d",
|
| + (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
|
| + } else {
|
| + [destStr appendFormat:@"%C", aChar];
|
| + }
|
| break;
|
| }
|
| }
|
| @@ -1133,6 +1188,8 @@ static void AppendTextFormatForMapMessageField(
|
| [toStr appendString:@"\n"];
|
|
|
| [toStr appendString:valueLine];
|
| +#pragma clang diagnostic push
|
| +#pragma clang diagnostic ignored "-Wswitch-enum"
|
| switch (valueDataType) {
|
| case GPBDataTypeString:
|
| AppendStringEscaped(value, toStr);
|
| @@ -1153,6 +1210,7 @@ static void AppendTextFormatForMapMessageField(
|
| NSCAssert(NO, @"Can't happen");
|
| break;
|
| }
|
| +#pragma clang diagnostic pop
|
| [toStr appendString:@"\n"];
|
|
|
| [toStr appendString:msgEnd];
|
| @@ -1174,6 +1232,8 @@ static void AppendTextFormatForMapMessageField(
|
| }
|
|
|
| [toStr appendString:valueLine];
|
| +#pragma clang diagnostic push
|
| +#pragma clang diagnostic ignored "-Wswitch-enum"
|
| switch (valueDataType) {
|
| case GPBDataTypeString:
|
| AppendStringEscaped(valueObj, toStr);
|
| @@ -1211,6 +1271,7 @@ static void AppendTextFormatForMapMessageField(
|
| [toStr appendString:valueObj];
|
| break;
|
| }
|
| +#pragma clang diagnostic pop
|
| [toStr appendString:@"\n"];
|
|
|
| [toStr appendString:msgEnd];
|
| @@ -1480,7 +1541,8 @@ static void AppendTextFormatForMessage(GPBMessage *message,
|
| NSUInteger fieldCount = fieldsArray.count;
|
| const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
|
| NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
|
| - NSArray *activeExtensions = [message sortedExtensionsInUse];
|
| + NSArray *activeExtensions = [[message extensionsCurrentlySet]
|
| + sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
|
| for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
|
| if (i == fieldCount) {
|
| AppendTextFormatForMessageExtensionRange(
|
| @@ -1706,6 +1768,8 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
|
| return result;
|
| }
|
|
|
| +#pragma clang diagnostic pop
|
| +
|
| #pragma mark - GPBMessageSignatureProtocol
|
|
|
| // A series of selectors that are used solely to get @encoding values
|
|
|