From d846b0b059b4d867536b98aa29475a387aa09114 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 8 Jun 2015 16:24:57 -0400 Subject: Beta quality drop of Objective C Support. - Add more to the ObjC dir readme. - Merge the ExtensionField and ExtensionDescriptor to reduce overhead. - Fix an initialization race. - Clean up the Xcode schemes. - Remove the class/enum filter. - Remove some forced inline that were bloating things without proof of performance wins. - Rename some internal types to avoid conflicts with the well know types protos. - Drop the use of ApplyFunctions to the compiler/optimizer can do what it wants. - Better document some possible future improvements. - Add missing support for parsing repeated primitive fields in packed or unpacked forms. - Improve -hash. - Add *Count for repeated and map<> fields to avoid auto create when checking for them being set. --- objectivec/GPBExtensionField.m | 525 ----------------------------------------- 1 file changed, 525 deletions(-) delete mode 100644 objectivec/GPBExtensionField.m (limited to 'objectivec/GPBExtensionField.m') diff --git a/objectivec/GPBExtensionField.m b/objectivec/GPBExtensionField.m deleted file mode 100644 index bbb36d7f..00000000 --- a/objectivec/GPBExtensionField.m +++ /dev/null @@ -1,525 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#import "GPBExtensionField_PackagePrivate.h" - -#import - -#import "GPBCodedInputStream_PackagePrivate.h" -#import "GPBCodedOutputStream.h" -#import "GPBDescriptor_PackagePrivate.h" -#import "GPBMessage_PackagePrivate.h" -#import "GPBUtilities_PackagePrivate.h" - -GPB_INLINE size_t TypeSize(GPBType type) { - switch (type) { - case GPBTypeBool: - return 1; - case GPBTypeFixed32: - case GPBTypeSFixed32: - case GPBTypeFloat: - return 4; - case GPBTypeFixed64: - case GPBTypeSFixed64: - case GPBTypeDouble: - return 8; - default: - return 0; - } -} - -GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) { - return (description->options & GPBExtensionRepeated) != 0; -} - -GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) { - return (description->options & GPBExtensionPacked) != 0; -} - -GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) { - return (description->options & GPBExtensionSetWireFormat) != 0; -} - -static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##SizeNoTag(object); - switch (type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Message) - FIELD_CASE2(Group) - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static size_t ComputeSerializedSizeIncludingTagOfObject( - GPBExtensionDescription *description, id object) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##Size(description->fieldNumber, \ - [(NSNumber *)object ACCESSOR]); -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##Size(description->fieldNumber, object); - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Group) - case GPBTypeMessage: - if (ExtensionIsWireFormat(description)) { - return GPBComputeMessageSetExtensionSize(description->fieldNumber, - object); - } else { - return GPBComputeMessageSize(description->fieldNumber, object); - } - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static size_t ComputeSerializedSizeIncludingTagOfArray( - GPBExtensionDescription *description, NSArray *values) { - if (ExtensionIsPacked(description)) { - size_t size = 0; - size_t typeSize = TypeSize(description->type); - if (typeSize != 0) { - size = values.count * typeSize; - } else { - for (id value in values) { - size += ComputePBSerializedSizeNoTagOfObject(description->type, value); - } - } - return size + GPBComputeTagSize(description->fieldNumber) + - GPBComputeRawVarint32SizeForInteger(size); - } else { - size_t size = 0; - for (id value in values) { - size += ComputeSerializedSizeIncludingTagOfObject(description, value); - } - return size; - } -} - -static void WriteObjectIncludingTagToCodedOutputStream( - id object, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - [output write##TYPE:description->fieldNumber \ - value:[(NSNumber *)object ACCESSOR]]; \ - return; -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - [output write##TYPE:description->fieldNumber value:object]; \ - return; - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Group) - case GPBTypeMessage: - if (ExtensionIsWireFormat(description)) { - [output writeMessageSetExtension:description->fieldNumber value:object]; - } else { - [output writeMessage:description->fieldNumber value:object]; - } - return; - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static void WriteObjectNoTagToCodedOutputStream( - id object, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ - return; -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - [output write##TYPE##NoTag:object]; \ - return; - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Message) - case GPBTypeGroup: - [output writeGroupNoTag:description->fieldNumber value:object]; - return; - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static void WriteArrayIncludingTagsToCodedOutputStream( - NSArray *values, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { - if (ExtensionIsPacked(description)) { - [output writeTag:description->fieldNumber - format:GPBWireFormatLengthDelimited]; - size_t dataSize = 0; - size_t typeSize = TypeSize(description->type); - if (typeSize != 0) { - dataSize = values.count * typeSize; - } else { - for (id value in values) { - dataSize += - ComputePBSerializedSizeNoTagOfObject(description->type, value); - } - } - [output writeRawVarintSizeTAs32:dataSize]; - for (id value in values) { - WriteObjectNoTagToCodedOutputStream(value, description, output); - } - } else { - for (id value in values) { - WriteObjectIncludingTagToCodedOutputStream(value, description, output); - } - } -} - -@implementation GPBExtensionField { - GPBExtensionDescription *description_; - GPBExtensionDescriptor *descriptor_; - GPBValue defaultValue_; -} - -@synthesize containingType = containingType_; -@synthesize descriptor = descriptor_; - -- (instancetype)init { - // Throw an exception if people attempt to not use the designated initializer. - self = [super init]; - if (self != nil) { - [self doesNotRecognizeSelector:_cmd]; - self = nil; - } - return self; -} - -- (instancetype)initWithDescription:(GPBExtensionDescription *)description { - if ((self = [super init])) { - description_ = description; - if (description->extendedClass) { - Class containingClass = objc_lookUpClass(description->extendedClass); - NSAssert1(containingClass, @"Class %s not defined", - description->extendedClass); - containingType_ = [containingClass descriptor]; - } -#if DEBUG - const char *className = description->messageOrGroupClassName; - if (className) { - NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined", - className); - } -#endif - descriptor_ = [[GPBExtensionDescriptor alloc] - initWithExtensionDescription:description]; - GPBType type = description_->type; - if (type == GPBTypeData) { - // Data stored as a length prefixed c-string in descriptor records. - const uint8_t *bytes = - (const uint8_t *)description->defaultValue.valueData; - if (bytes) { - uint32_t length = *((uint32_t *)bytes); - // The length is stored in network byte order. - length = ntohl(length); - bytes += sizeof(length); - defaultValue_.valueData = - [[NSData alloc] initWithBytes:bytes length:length]; - } - } else if (type == GPBTypeMessage || type == GPBTypeGroup) { - // The default is looked up in -defaultValue instead since extensions - // aren't - // common, we avoid the hit startup hit and it avoid initialization order - // issues. - } else { - defaultValue_ = description->defaultValue; - } - } - return self; -} - -- (void)dealloc { - if ((description_->type == GPBTypeData) && - !ExtensionIsRepeated(description_)) { - [defaultValue_.valueData release]; - } - [descriptor_ release]; - [super dealloc]; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@", - [self class], self, self.fieldNumber, - self.containingType]; -} - -- (id)copyWithZone:(NSZone *)__unused zone { - return [self retain]; -} - -#pragma mark Properties - -- (int32_t)fieldNumber { - return description_->fieldNumber; -} - -- (GPBWireFormat)wireType { - return GPBWireFormatForType(description_->type, - ExtensionIsPacked(description_)); -} - -- (BOOL)isRepeated { - return ExtensionIsRepeated(description_); -} - -- (id)defaultValue { - if (ExtensionIsRepeated(description_)) { - return nil; - } - - switch (description_->type) { - case GPBTypeBool: - return @(defaultValue_.valueBool); - case GPBTypeFloat: - return @(defaultValue_.valueFloat); - case GPBTypeDouble: - return @(defaultValue_.valueDouble); - case GPBTypeInt32: - case GPBTypeSInt32: - case GPBTypeEnum: - case GPBTypeSFixed32: - return @(defaultValue_.valueInt32); - case GPBTypeInt64: - case GPBTypeSInt64: - case GPBTypeSFixed64: - return @(defaultValue_.valueInt64); - case GPBTypeUInt32: - case GPBTypeFixed32: - return @(defaultValue_.valueUInt32); - case GPBTypeUInt64: - case GPBTypeFixed64: - return @(defaultValue_.valueUInt64); - case GPBTypeData: - // Like message fields, the default is zero length data. - return (defaultValue_.valueData ? defaultValue_.valueData - : GPBEmptyNSData()); - case GPBTypeString: - // Like message fields, the default is zero length string. - return (defaultValue_.valueString ? defaultValue_.valueString : @""); - case GPBTypeGroup: - case GPBTypeMessage: - NSAssert(0, @"Shouldn't get here"); - return nil; - } -} - -#pragma mark Internals - -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - message:(GPBMessage *)message { - GPBCodedInputStreamState *state = &input->state_; - if (ExtensionIsPacked(description_)) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - id value = [self newSingleValueFromCodedInputStream:input - extensionRegistry:extensionRegistry - existingValue:nil]; - [message addExtension:self value:value]; - [value release]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - id existingValue = nil; - BOOL isRepeated = ExtensionIsRepeated(description_); - if (!isRepeated && GPBTypeIsMessage(description_->type)) { - existingValue = [message getExistingExtension:self]; - } - id value = [self newSingleValueFromCodedInputStream:input - extensionRegistry:extensionRegistry - existingValue:existingValue]; - if (isRepeated) { - [message addExtension:self value:value]; - } else { - [message setExtension:self value:value]; - } - [value release]; - } -} - -- (void)writeValue:(id)value - includingTagToCodedOutputStream:(GPBCodedOutputStream *)output { - if (ExtensionIsRepeated(description_)) { - WriteArrayIncludingTagsToCodedOutputStream(value, description_, output); - } else { - WriteObjectIncludingTagToCodedOutputStream(value, description_, output); - } -} - -- (size_t)computeSerializedSizeIncludingTag:(id)value { - if (ExtensionIsRepeated(description_)) { - return ComputeSerializedSizeIncludingTagOfArray(description_, value); - } else { - return ComputeSerializedSizeIncludingTagOfObject(description_, value); - } -} - -// Note that this returns a retained value intentionally. -- (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - existingValue:(GPBMessage *)existingValue { - GPBCodedInputStreamState *state = &input->state_; - switch (description_->type) { - case GPBTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; - case GPBTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; - case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; - case GPBTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; - case GPBTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; - case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; - case GPBTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; - case GPBTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; - case GPBTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; - case GPBTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; - case GPBTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; - case GPBTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; - case GPBTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; - case GPBTypeData: return GPBCodedInputStreamReadRetainedData(state); - case GPBTypeString: return GPBCodedInputStreamReadRetainedString(state); - case GPBTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; - case GPBTypeGroup: - case GPBTypeMessage: { - GPBMessage *message; - if (existingValue) { - message = [existingValue retain]; - } else { - GPBDescriptor *decriptor = [descriptor_.msgClass descriptor]; - message = [[decriptor.messageClass alloc] init]; - } - - if (description_->type == GPBTypeGroup) { - [input readGroup:description_->fieldNumber - message:message - extensionRegistry:extensionRegistry]; - } else { - // description_->type == GPBTypeMessage - if (ExtensionIsWireFormat(description_)) { - // For MessageSet fields the message length will have already been - // read. - [message mergeFromCodedInputStream:input - extensionRegistry:extensionRegistry]; - } else { - [input readMessage:message extensionRegistry:extensionRegistry]; - } - } - - return message; - } - } - - return nil; -} - -- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other { - int32_t selfNumber = description_->fieldNumber; - int32_t otherNumber = other->description_->fieldNumber; - if (selfNumber < otherNumber) { - return NSOrderedAscending; - } else if (selfNumber == otherNumber) { - return NSOrderedSame; - } else { - return NSOrderedDescending; - } -} - -@end -- cgit v1.2.3