diff options
Diffstat (limited to 'objectivec/GPBDescriptor.m')
-rw-r--r-- | objectivec/GPBDescriptor.m | 992 |
1 files changed, 0 insertions, 992 deletions
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m deleted file mode 100644 index dccb9bc8..00000000 --- a/objectivec/GPBDescriptor.m +++ /dev/null @@ -1,992 +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 "GPBDescriptor_PackagePrivate.h" - -#import <objc/runtime.h> - -#import "GPBUtilities_PackagePrivate.h" -#import "GPBWireFormat.h" -#import "GPBMessage_PackagePrivate.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" - -// The address of this variable is used as a key for obj_getAssociatedObject. -static const char kTextFormatExtraValueKey = 0; - -// Utility function to generate selectors on the fly. -static SEL SelFromStrings(const char *prefix, const char *middle, - const char *suffix, BOOL takesArg) { - if (prefix == NULL && suffix == NULL && !takesArg) { - return sel_getUid(middle); - } - const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; - const size_t middleLen = strlen(middle); - const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; - size_t totalLen = - prefixLen + middleLen + suffixLen + 1; // include space for null on end. - if (takesArg) { - totalLen += 1; - } - char buffer[totalLen]; - if (prefix != NULL) { - memcpy(buffer, prefix, prefixLen); - memcpy(buffer + prefixLen, middle, middleLen); - buffer[prefixLen] = (char)toupper(buffer[prefixLen]); - } else { - memcpy(buffer, middle, middleLen); - } - if (suffix != NULL) { - memcpy(buffer + prefixLen + middleLen, suffix, suffixLen); - } - if (takesArg) { - buffer[totalLen - 2] = ':'; - } - // Always null terminate it. - buffer[totalLen - 1] = 0; - - SEL result = sel_getUid(buffer); - return result; -} - -static NSArray *NewFieldsArrayForHasIndex(int hasIndex, - NSArray *allMessageFields) - __attribute__((ns_returns_retained)); - -static NSArray *NewFieldsArrayForHasIndex(int hasIndex, - NSArray *allMessageFields) { - NSMutableArray *result = [[NSMutableArray alloc] init]; - for (GPBFieldDescriptor *fieldDesc in allMessageFields) { - if (fieldDesc->description_->hasIndex == hasIndex) { - [result addObject:fieldDesc]; - } - } - return result; -} - -@implementation GPBDescriptor { - Class messageClass_; - GPBFileDescriptor *file_; - BOOL wireFormat_; -} - -@synthesize messageClass = messageClass_; -@synthesize fields = fields_; -@synthesize oneofs = oneofs_; -@synthesize extensionRanges = extensionRanges_; -@synthesize extensionRangesCount = extensionRangesCount_; -@synthesize file = file_; -@synthesize wireFormat = wireFormat_; - -+ (instancetype) - allocDescriptorForClass:(Class)messageClass - rootClass:(Class)rootClass - file:(GPBFileDescriptor *)file - fields:(void *)fieldDescriptions - fieldCount:(uint32_t)fieldCount - storageSize:(uint32_t)storageSize - flags:(GPBDescriptorInitializationFlags)flags { - // The rootClass is no longer used, but it is passed in to ensure it - // was started up during initialization also. - (void)rootClass; - NSMutableArray *fields = nil; - GPBFileSyntax syntax = file.syntax; - BOOL fieldsIncludeDefault = - (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; - - void *desc; - for (uint32_t i = 0; i < fieldCount; ++i) { - if (fields == nil) { - fields = [[NSMutableArray alloc] initWithCapacity:fieldCount]; - } - // Need correctly typed pointer for array indexing below to work. - if (fieldsIncludeDefault) { - GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions; - desc = &(fieldDescWithDefault[i]); - } else { - GPBMessageFieldDescription *fieldDesc = fieldDescriptions; - desc = &(fieldDesc[i]); - } - GPBFieldDescriptor *fieldDescriptor = - [[GPBFieldDescriptor alloc] initWithFieldDescription:desc - includesDefault:fieldsIncludeDefault - syntax:syntax]; - [fields addObject:fieldDescriptor]; - [fieldDescriptor release]; - } - - BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0; - GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass - file:file - fields:fields - storageSize:storageSize - wireFormat:wireFormat]; - [fields release]; - return descriptor; -} - -- (instancetype)initWithClass:(Class)messageClass - file:(GPBFileDescriptor *)file - fields:(NSArray *)fields - storageSize:(uint32_t)storageSize - wireFormat:(BOOL)wireFormat { - if ((self = [super init])) { - messageClass_ = messageClass; - file_ = file; - fields_ = [fields retain]; - storageSize_ = storageSize; - wireFormat_ = wireFormat; - } - return self; -} - -- (void)dealloc { - [fields_ release]; - [oneofs_ release]; - [super dealloc]; -} - -- (void)setupOneofs:(const char **)oneofNames - count:(uint32_t)count - firstHasIndex:(int32_t)firstHasIndex { - NSCAssert(firstHasIndex < 0, @"Should always be <0"); - NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count]; - for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) { - const char *name = oneofNames[i]; - NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_); - NSCAssert(fieldsForOneof.count > 0, - @"No fields for this oneof? (%s:%d)", name, hasIndex); - GPBOneofDescriptor *oneofDescriptor = - [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof]; - [oneofs addObject:oneofDescriptor]; - [oneofDescriptor release]; - [fieldsForOneof release]; - } - oneofs_ = oneofs; -} - -- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo { - // Extra info is a compile time option, so skip the work if not needed. - if (extraTextFormatInfo) { - NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo]; - for (GPBFieldDescriptor *fieldDescriptor in fields_) { - if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) { - objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, - extraInfoValue, - OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - } - } -} - -- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count { - extensionRanges_ = ranges; - extensionRangesCount_ = count; -} - -- (NSString *)name { - return NSStringFromClass(messageClass_); -} - -- (id)copyWithZone:(NSZone *)zone { -#pragma unused(zone) - return [self retain]; -} - -- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { - for (GPBFieldDescriptor *descriptor in fields_) { - if (GPBFieldNumber(descriptor) == fieldNumber) { - return descriptor; - } - } - return nil; -} - -- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { - for (GPBFieldDescriptor *descriptor in fields_) { - if ([descriptor.name isEqual:name]) { - return descriptor; - } - } - return nil; -} - -- (GPBOneofDescriptor *)oneofWithName:(NSString *)name { - for (GPBOneofDescriptor *descriptor in oneofs_) { - if ([descriptor.name isEqual:name]) { - return descriptor; - } - } - return nil; -} - -@end - -@implementation GPBFileDescriptor { - NSString *package_; - GPBFileSyntax syntax_; -} - -@synthesize package = package_; -@synthesize syntax = syntax_; - -- (instancetype)initWithPackage:(NSString *)package - syntax:(GPBFileSyntax)syntax { - self = [super init]; - if (self) { - package_ = [package copy]; - syntax_ = syntax; - } - return self; -} - -- (void)dealloc { - [package_ release]; - [super dealloc]; -} - -@end - -@implementation GPBOneofDescriptor - -@synthesize fields = fields_; - -- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { - self = [super init]; - if (self) { - name_ = name; - fields_ = [fields retain]; - for (GPBFieldDescriptor *fieldDesc in fields) { - fieldDesc->containingOneof_ = self; - } - - caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO); - } - return self; -} - -- (void)dealloc { - [fields_ release]; - [super dealloc]; -} - -- (NSString *)name { - return @(name_); -} - -- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { - for (GPBFieldDescriptor *descriptor in fields_) { - if (GPBFieldNumber(descriptor) == fieldNumber) { - return descriptor; - } - } - return nil; -} - -- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { - for (GPBFieldDescriptor *descriptor in fields_) { - if ([descriptor.name isEqual:name]) { - return descriptor; - } - } - return nil; -} - -@end - -uint32_t GPBFieldTag(GPBFieldDescriptor *self) { - GPBMessageFieldDescription *description = self->description_; - GPBWireFormat format; - if ((description->flags & GPBFieldMapKeyMask) != 0) { - // Maps are repeated messages on the wire. - format = GPBWireFormatForType(GPBDataTypeMessage, NO); - } else { - format = GPBWireFormatForType(description->dataType, - ((description->flags & GPBFieldPacked) != 0)); - } - return GPBWireFormatMakeTag(description->number, format); -} - -uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { - GPBMessageFieldDescription *description = self->description_; - NSCAssert((description->flags & GPBFieldRepeated) != 0, - @"Only valid on repeated fields"); - GPBWireFormat format = - GPBWireFormatForType(description->dataType, - ((description->flags & GPBFieldPacked) == 0)); - return GPBWireFormatMakeTag(description->number, format); -} - -@implementation GPBFieldDescriptor { - GPBGenericValue defaultValue_; - - // Message ivars - Class msgClass_; - - // Enum ivars. - // If protos are generated with GenerateEnumDescriptors on then it will - // be a enumDescriptor, otherwise it will be a enumVerifier. - union { - GPBEnumDescriptor *enumDescriptor_; - GPBEnumValidationFunc enumVerifier_; - } enumHandling_; -} - -@synthesize msgClass = msgClass_; -@synthesize containingOneof = containingOneof_; - -- (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)initWithFieldDescription:(void *)description - includesDefault:(BOOL)includesDefault - syntax:(GPBFileSyntax)syntax { - if ((self = [super init])) { - GPBMessageFieldDescription *coreDesc; - if (includesDefault) { - coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core); - } else { - coreDesc = description; - } - description_ = coreDesc; - getSel_ = sel_getUid(coreDesc->name); - setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES); - - GPBDataType dataType = coreDesc->dataType; - BOOL isMessage = GPBDataTypeIsMessage(dataType); - BOOL isMapOrArray = GPBFieldIsMapOrArray(self); - - if (isMapOrArray) { - // map<>/repeated fields get a *Count property (inplace of a has*) to - // support checking if there are any entries without triggering - // autocreation. - hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); - } else { - // If there is a positive hasIndex, then: - // - All fields types for proto2 messages get has* selectors. - // - Only message fields for proto3 messages get has* selectors. - // Note: the positive check is to handle oneOfs, we can't check - // containingOneof_ because it isn't set until after initialization. - if ((coreDesc->hasIndex >= 0) && - (coreDesc->hasIndex != GPBNoHasBit) && - ((syntax != GPBFileSyntaxProto3) || isMessage)) { - hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); - setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); - } - } - - // Extra type specific data. - if (isMessage) { - const char *className = coreDesc->dataTypeSpecific.className; - msgClass_ = objc_getClass(className); - NSAssert(msgClass_, @"Class %s not defined", className); - } else if (dataType == GPBDataTypeEnum) { - if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { - enumHandling_.enumDescriptor_ = - coreDesc->dataTypeSpecific.enumDescFunc(); - } else { - enumHandling_.enumVerifier_ = - coreDesc->dataTypeSpecific.enumVerifier; - } - } - - // Non map<>/repeated fields can have defaults in proto2 syntax. - if (!isMapOrArray && includesDefault) { - defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; - if (dataType == GPBDataTypeBytes) { - // Data stored as a length prefixed (network byte order) c-string in - // descriptor structure. - const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; - if (bytes) { - uint32_t length = *((uint32_t *)bytes); - length = ntohl(length); - bytes += sizeof(length); - defaultValue_.valueData = - [[NSData alloc] initWithBytes:bytes length:length]; - } - } - } - } - return self; -} - -- (void)dealloc { - if (description_->dataType == GPBDataTypeBytes && - !(description_->flags & GPBFieldRepeated)) { - [defaultValue_.valueData release]; - } - [super dealloc]; -} - -- (GPBDataType)dataType { - return description_->dataType; -} - -- (BOOL)hasDefaultValue { - return (description_->flags & GPBFieldHasDefaultValue) != 0; -} - -- (uint32_t)number { - return description_->number; -} - -- (NSString *)name { - return @(description_->name); -} - -- (BOOL)isRequired { - return (description_->flags & GPBFieldRequired) != 0; -} - -- (BOOL)isOptional { - return (description_->flags & GPBFieldOptional) != 0; -} - -- (GPBFieldType)fieldType { - GPBFieldFlags flags = description_->flags; - if ((flags & GPBFieldRepeated) != 0) { - return GPBFieldTypeRepeated; - } else if ((flags & GPBFieldMapKeyMask) != 0) { - return GPBFieldTypeMap; - } else { - return GPBFieldTypeSingle; - } -} - -- (GPBDataType)mapKeyDataType { - switch (description_->flags & GPBFieldMapKeyMask) { - case GPBFieldMapKeyInt32: - return GPBDataTypeInt32; - case GPBFieldMapKeyInt64: - return GPBDataTypeInt64; - case GPBFieldMapKeyUInt32: - return GPBDataTypeUInt32; - case GPBFieldMapKeyUInt64: - return GPBDataTypeUInt64; - case GPBFieldMapKeySInt32: - return GPBDataTypeSInt32; - case GPBFieldMapKeySInt64: - return GPBDataTypeSInt64; - case GPBFieldMapKeyFixed32: - return GPBDataTypeFixed32; - case GPBFieldMapKeyFixed64: - return GPBDataTypeFixed64; - case GPBFieldMapKeySFixed32: - return GPBDataTypeSFixed32; - case GPBFieldMapKeySFixed64: - return GPBDataTypeSFixed64; - case GPBFieldMapKeyBool: - return GPBDataTypeBool; - case GPBFieldMapKeyString: - return GPBDataTypeString; - - default: - NSAssert(0, @"Not a map type"); - return GPBDataTypeInt32; // For lack of anything better. - } -} - -- (BOOL)isPackable { - return (description_->flags & GPBFieldPacked) != 0; -} - -- (BOOL)isValidEnumValue:(int32_t)value { - NSAssert(description_->dataType == GPBDataTypeEnum, - @"Field Must be of type GPBDataTypeEnum"); - if (description_->flags & GPBFieldHasEnumDescriptor) { - return enumHandling_.enumDescriptor_.enumVerifier(value); - } else { - return enumHandling_.enumVerifier_(value); - } -} - -- (GPBEnumDescriptor *)enumDescriptor { - if (description_->flags & GPBFieldHasEnumDescriptor) { - return enumHandling_.enumDescriptor_; - } else { - return nil; - } -} - -- (GPBGenericValue)defaultValue { - // Depends on the fact that defaultValue_ is initialized either to "0/nil" or - // to an actual defaultValue in our initializer. - GPBGenericValue value = defaultValue_; - - if (!(description_->flags & GPBFieldRepeated)) { - // We special handle data and strings. If they are nil, we replace them - // with empty string/empty data. - GPBDataType type = description_->dataType; - if (type == GPBDataTypeBytes && value.valueData == nil) { - value.valueData = GPBEmptyNSData(); - } else if (type == GPBDataTypeString && value.valueString == nil) { - value.valueString = @""; - } - } - return value; -} - -- (NSString *)textFormatName { - if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) { - NSValue *extraInfoValue = - objc_getAssociatedObject(self, &kTextFormatExtraValueKey); - // Support can be left out at generation time. - if (!extraInfoValue) { - return nil; - } - const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue]; - return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), - self.name); - } - - // The logic here has to match SetCommonFieldVariables() from - // objectivec_field.cc in the proto compiler. - NSString *name = self.name; - NSUInteger len = [name length]; - - // Remove the "_p" added to reserved names. - if ([name hasSuffix:@"_p"]) { - name = [name substringToIndex:(len - 2)]; - len = [name length]; - } - - // Remove "Array" from the end for repeated fields. - if (((description_->flags & GPBFieldRepeated) != 0) && - [name hasSuffix:@"Array"]) { - name = [name substringToIndex:(len - 5)]; - len = [name length]; - } - - // Groups vs. other fields. - if (description_->dataType == GPBDataTypeGroup) { - // Just capitalize the first letter. - unichar firstChar = [name characterAtIndex:0]; - if (firstChar >= 'a' && firstChar <= 'z') { - NSString *firstCharString = - [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')]; - NSString *result = - [name stringByReplacingCharactersInRange:NSMakeRange(0, 1) - withString:firstCharString]; - return result; - } - return name; - - } else { - // Undo the CamelCase. - NSMutableString *result = [NSMutableString stringWithCapacity:len]; - for (uint32_t i = 0; i < len; i++) { - unichar c = [name characterAtIndex:i]; - if (c >= 'A' && c <= 'Z') { - if (i > 0) { - [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')]; - } else { - [result appendFormat:@"%C", c]; - } - } else { - [result appendFormat:@"%C", c]; - } - } - return result; - } -} - -@end - -@implementation GPBEnumDescriptor { - NSString *name_; - // valueNames_ is a single c string with all of the value names appended - // together, each null terminated. -calcValueNameOffsets fills in - // nameOffsets_ with the offsets to allow quicker access to the individual - // names. - const char *valueNames_; - const int32_t *values_; - GPBEnumValidationFunc enumVerifier_; - const uint8_t *extraTextFormatInfo_; - uint32_t *nameOffsets_; - uint32_t valueCount_; -} - -@synthesize name = name_; -@synthesize enumVerifier = enumVerifier_; - -+ (instancetype) - allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier { - GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name - valueNames:valueNames - values:values - count:valueCount - enumVerifier:enumVerifier]; - return descriptor; -} - -+ (instancetype) - allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier - extraTextFormatInfo:(const char *)extraTextFormatInfo { - // Call the common case. - GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name - valueNames:valueNames - values:values - count:valueCount - enumVerifier:enumVerifier]; - // Set the extra info. - descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo; - return descriptor; -} - -- (instancetype)initWithName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier { - if ((self = [super init])) { - name_ = [name copy]; - valueNames_ = valueNames; - values_ = values; - valueCount_ = valueCount; - enumVerifier_ = enumVerifier; - } - return self; -} - -- (void)dealloc { - [name_ release]; - if (nameOffsets_) free(nameOffsets_); - [super dealloc]; -} - -- (void)calcValueNameOffsets { - @synchronized(self) { - if (nameOffsets_ != NULL) { - return; - } - uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); - const char *scan = valueNames_; - for (uint32_t i = 0; i < valueCount_; ++i) { - offsets[i] = (uint32_t)(scan - valueNames_); - while (*scan != '\0') ++scan; - ++scan; // Step over the null. - } - nameOffsets_ = offsets; - } -} - -- (NSString *)enumNameForValue:(int32_t)number { - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - - for (uint32_t i = 0; i < valueCount_; ++i) { - if (values_[i] == number) { - const char *valueName = valueNames_ + nameOffsets_[i]; - NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; - return fullName; - } - } - return nil; -} - -- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { - // Must have the prefix. - NSUInteger prefixLen = name_.length + 1; - if ((name.length <= prefixLen) || ![name hasPrefix:name_] || - ([name characterAtIndex:prefixLen - 1] != '_')) { - return NO; - } - - // Skip over the prefix. - const char *nameAsCStr = [name UTF8String]; - nameAsCStr += prefixLen; - - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - - // Find it. - for (uint32_t i = 0; i < valueCount_; ++i) { - const char *valueName = valueNames_ + nameOffsets_[i]; - if (strcmp(nameAsCStr, valueName) == 0) { - if (outValue) { - *outValue = values_[i]; - } - return YES; - } - } - return NO; -} - -- (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - - for (uint32_t i = 0; i < valueCount_; ++i) { - int32_t value = values_[i]; - NSString *valueTextFormatName = [self textFormatNameForValue:value]; - if ([valueTextFormatName isEqual:textFormatName]) { - if (outValue) { - *outValue = value; - } - return YES; - } - } - return NO; -} - -- (NSString *)textFormatNameForValue:(int32_t)number { - if (nameOffsets_ == NULL) [self calcValueNameOffsets]; - - // Find the EnumValue descriptor and its index. - BOOL foundIt = NO; - uint32_t valueDescriptorIndex; - for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; - ++valueDescriptorIndex) { - if (values_[valueDescriptorIndex] == number) { - foundIt = YES; - break; - } - } - - if (!foundIt) { - return nil; - } - - NSString *result = nil; - // Naming adds an underscore between enum name and value name, skip that also. - const char *valueName = valueNames_ + nameOffsets_[valueDescriptorIndex]; - NSString *shortName = @(valueName); - - // See if it is in the map of special format handling. - if (extraTextFormatInfo_) { - result = GPBDecodeTextFormatName(extraTextFormatInfo_, - (int32_t)valueDescriptorIndex, shortName); - } - // Logic here needs to match what objectivec_enum.cc does in the proto - // compiler. - if (result == nil) { - NSUInteger len = [shortName length]; - NSMutableString *worker = [NSMutableString stringWithCapacity:len]; - for (NSUInteger i = 0; i < len; i++) { - unichar c = [shortName characterAtIndex:i]; - if (i > 0 && c >= 'A' && c <= 'Z') { - [worker appendString:@"_"]; - } - [worker appendFormat:@"%c", toupper((char)c)]; - } - result = worker; - } - return result; -} - -@end - -@implementation GPBExtensionDescriptor { - GPBGenericValue defaultValue_; -} - -@synthesize containingMessageClass = containingMessageClass_; - -- (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description { - if ((self = [super init])) { - description_ = description; - -#if defined(DEBUG) && DEBUG - const char *className = description->messageOrGroupClassName; - if (className) { - NSAssert(objc_lookUpClass(className) != Nil, - @"Class %s not defined", className); - } -#endif - - if (description->extendedClass) { - Class containingClass = objc_lookUpClass(description->extendedClass); - NSAssert(containingClass, @"Class %s not defined", - description->extendedClass); - containingMessageClass_ = containingClass; - } - - GPBDataType type = description_->dataType; - if (type == GPBDataTypeBytes) { - // 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 == GPBDataTypeMessage || type == GPBDataTypeGroup) { - // 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_->dataType == GPBDataTypeBytes) && - !GPBExtensionIsRepeated(description_)) { - [defaultValue_.valueData release]; - } - [super dealloc]; -} - -- (instancetype)copyWithZone:(NSZone *)zone { -#pragma unused(zone) - // Immutable. - return [self retain]; -} - -- (NSString *)singletonName { - return @(description_->singletonName); -} - -- (const char *)singletonNameC { - return description_->singletonName; -} - -- (uint32_t)fieldNumber { - return description_->fieldNumber; -} - -- (GPBDataType)dataType { - return description_->dataType; -} - -- (GPBWireFormat)wireType { - return GPBWireFormatForType(description_->dataType, - GPBExtensionIsPacked(description_)); -} - -- (GPBWireFormat)alternateWireType { - NSAssert(GPBExtensionIsRepeated(description_), - @"Only valid on repeated extensions"); - return GPBWireFormatForType(description_->dataType, - !GPBExtensionIsPacked(description_)); -} - -- (BOOL)isRepeated { - return GPBExtensionIsRepeated(description_); -} - -- (BOOL)isMap { - return (description_->options & GPBFieldMapKeyMask) != 0; -} - -- (BOOL)isPackable { - return GPBExtensionIsPacked(description_); -} - -- (Class)msgClass { - return objc_getClass(description_->messageOrGroupClassName); -} - -- (GPBEnumDescriptor *)enumDescriptor { - if (description_->dataType == GPBDataTypeEnum) { - GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); - return enumDescriptor; - } - return nil; -} - -- (id)defaultValue { - if (GPBExtensionIsRepeated(description_)) { - return nil; - } - - switch (description_->dataType) { - case GPBDataTypeBool: - return @(defaultValue_.valueBool); - case GPBDataTypeFloat: - return @(defaultValue_.valueFloat); - case GPBDataTypeDouble: - return @(defaultValue_.valueDouble); - case GPBDataTypeInt32: - case GPBDataTypeSInt32: - case GPBDataTypeEnum: - case GPBDataTypeSFixed32: - return @(defaultValue_.valueInt32); - case GPBDataTypeInt64: - case GPBDataTypeSInt64: - case GPBDataTypeSFixed64: - return @(defaultValue_.valueInt64); - case GPBDataTypeUInt32: - case GPBDataTypeFixed32: - return @(defaultValue_.valueUInt32); - case GPBDataTypeUInt64: - case GPBDataTypeFixed64: - return @(defaultValue_.valueUInt64); - case GPBDataTypeBytes: - // Like message fields, the default is zero length data. - return (defaultValue_.valueData ? defaultValue_.valueData - : GPBEmptyNSData()); - case GPBDataTypeString: - // Like message fields, the default is zero length string. - return (defaultValue_.valueString ? defaultValue_.valueString : @""); - case GPBDataTypeGroup: - case GPBDataTypeMessage: - return nil; - } -} - -- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)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 - -#pragma clang diagnostic pop |