1*1b3f573fSAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format 2*1b3f573fSAndroid Build Coastguard Worker// Copyright 2008 Google Inc. All rights reserved. 3*1b3f573fSAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/ 4*1b3f573fSAndroid Build Coastguard Worker// 5*1b3f573fSAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without 6*1b3f573fSAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are 7*1b3f573fSAndroid Build Coastguard Worker// met: 8*1b3f573fSAndroid Build Coastguard Worker// 9*1b3f573fSAndroid Build Coastguard Worker// * Redistributions of source code must retain the above copyright 10*1b3f573fSAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer. 11*1b3f573fSAndroid Build Coastguard Worker// * Redistributions in binary form must reproduce the above 12*1b3f573fSAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer 13*1b3f573fSAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the 14*1b3f573fSAndroid Build Coastguard Worker// distribution. 15*1b3f573fSAndroid Build Coastguard Worker// * Neither the name of Google Inc. nor the names of its 16*1b3f573fSAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from 17*1b3f573fSAndroid Build Coastguard Worker// this software without specific prior written permission. 18*1b3f573fSAndroid Build Coastguard Worker// 19*1b3f573fSAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*1b3f573fSAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*1b3f573fSAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*1b3f573fSAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*1b3f573fSAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*1b3f573fSAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*1b3f573fSAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*1b3f573fSAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*1b3f573fSAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*1b3f573fSAndroid Build Coastguard Worker 31*1b3f573fSAndroid Build Coastguard Worker#import "GPBDescriptor_PackagePrivate.h" 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker#import <objc/runtime.h> 34*1b3f573fSAndroid Build Coastguard Worker 35*1b3f573fSAndroid Build Coastguard Worker#import "GPBUtilities_PackagePrivate.h" 36*1b3f573fSAndroid Build Coastguard Worker#import "GPBWireFormat.h" 37*1b3f573fSAndroid Build Coastguard Worker#import "GPBMessage_PackagePrivate.h" 38*1b3f573fSAndroid Build Coastguard Worker 39*1b3f573fSAndroid Build Coastguard Worker// Direct access is use for speed, to avoid even internally declaring things 40*1b3f573fSAndroid Build Coastguard Worker// read/write, etc. The warning is enabled in the project to ensure code calling 41*1b3f573fSAndroid Build Coastguard Worker// protos can turn on -Wdirect-ivar-access without issues. 42*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic push 43*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access" 44*1b3f573fSAndroid Build Coastguard Worker 45*1b3f573fSAndroid Build Coastguard Worker// The addresses of these variables are used as keys for objc_getAssociatedObject. 46*1b3f573fSAndroid Build Coastguard Workerstatic const char kTextFormatExtraValueKey = 0; 47*1b3f573fSAndroid Build Coastguard Workerstatic const char kParentClassValueKey = 0; 48*1b3f573fSAndroid Build Coastguard Workerstatic const char kClassNameSuffixKey = 0; 49*1b3f573fSAndroid Build Coastguard Worker 50*1b3f573fSAndroid Build Coastguard Worker// Utility function to generate selectors on the fly. 51*1b3f573fSAndroid Build Coastguard Workerstatic SEL SelFromStrings(const char *prefix, const char *middle, 52*1b3f573fSAndroid Build Coastguard Worker const char *suffix, BOOL takesArg) { 53*1b3f573fSAndroid Build Coastguard Worker if (prefix == NULL && suffix == NULL && !takesArg) { 54*1b3f573fSAndroid Build Coastguard Worker return sel_getUid(middle); 55*1b3f573fSAndroid Build Coastguard Worker } 56*1b3f573fSAndroid Build Coastguard Worker const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; 57*1b3f573fSAndroid Build Coastguard Worker const size_t middleLen = strlen(middle); 58*1b3f573fSAndroid Build Coastguard Worker const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; 59*1b3f573fSAndroid Build Coastguard Worker size_t totalLen = 60*1b3f573fSAndroid Build Coastguard Worker prefixLen + middleLen + suffixLen + 1; // include space for null on end. 61*1b3f573fSAndroid Build Coastguard Worker if (takesArg) { 62*1b3f573fSAndroid Build Coastguard Worker totalLen += 1; 63*1b3f573fSAndroid Build Coastguard Worker } 64*1b3f573fSAndroid Build Coastguard Worker char buffer[totalLen]; 65*1b3f573fSAndroid Build Coastguard Worker if (prefix != NULL) { 66*1b3f573fSAndroid Build Coastguard Worker memcpy(buffer, prefix, prefixLen); 67*1b3f573fSAndroid Build Coastguard Worker memcpy(buffer + prefixLen, middle, middleLen); 68*1b3f573fSAndroid Build Coastguard Worker buffer[prefixLen] = (char)toupper(buffer[prefixLen]); 69*1b3f573fSAndroid Build Coastguard Worker } else { 70*1b3f573fSAndroid Build Coastguard Worker memcpy(buffer, middle, middleLen); 71*1b3f573fSAndroid Build Coastguard Worker } 72*1b3f573fSAndroid Build Coastguard Worker if (suffix != NULL) { 73*1b3f573fSAndroid Build Coastguard Worker memcpy(buffer + prefixLen + middleLen, suffix, suffixLen); 74*1b3f573fSAndroid Build Coastguard Worker } 75*1b3f573fSAndroid Build Coastguard Worker if (takesArg) { 76*1b3f573fSAndroid Build Coastguard Worker buffer[totalLen - 2] = ':'; 77*1b3f573fSAndroid Build Coastguard Worker } 78*1b3f573fSAndroid Build Coastguard Worker // Always null terminate it. 79*1b3f573fSAndroid Build Coastguard Worker buffer[totalLen - 1] = 0; 80*1b3f573fSAndroid Build Coastguard Worker 81*1b3f573fSAndroid Build Coastguard Worker SEL result = sel_getUid(buffer); 82*1b3f573fSAndroid Build Coastguard Worker return result; 83*1b3f573fSAndroid Build Coastguard Worker} 84*1b3f573fSAndroid Build Coastguard Worker 85*1b3f573fSAndroid Build Coastguard Workerstatic NSArray *NewFieldsArrayForHasIndex(int hasIndex, 86*1b3f573fSAndroid Build Coastguard Worker NSArray *allMessageFields) 87*1b3f573fSAndroid Build Coastguard Worker __attribute__((ns_returns_retained)); 88*1b3f573fSAndroid Build Coastguard Worker 89*1b3f573fSAndroid Build Coastguard Workerstatic NSArray *NewFieldsArrayForHasIndex(int hasIndex, 90*1b3f573fSAndroid Build Coastguard Worker NSArray *allMessageFields) { 91*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *result = [[NSMutableArray alloc] init]; 92*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *fieldDesc in allMessageFields) { 93*1b3f573fSAndroid Build Coastguard Worker if (fieldDesc->description_->hasIndex == hasIndex) { 94*1b3f573fSAndroid Build Coastguard Worker [result addObject:fieldDesc]; 95*1b3f573fSAndroid Build Coastguard Worker } 96*1b3f573fSAndroid Build Coastguard Worker } 97*1b3f573fSAndroid Build Coastguard Worker return result; 98*1b3f573fSAndroid Build Coastguard Worker} 99*1b3f573fSAndroid Build Coastguard Worker 100*1b3f573fSAndroid Build Coastguard Worker@implementation GPBDescriptor { 101*1b3f573fSAndroid Build Coastguard Worker Class messageClass_; 102*1b3f573fSAndroid Build Coastguard Worker GPBFileDescriptor *file_; 103*1b3f573fSAndroid Build Coastguard Worker BOOL wireFormat_; 104*1b3f573fSAndroid Build Coastguard Worker} 105*1b3f573fSAndroid Build Coastguard Worker 106*1b3f573fSAndroid Build Coastguard Worker@synthesize messageClass = messageClass_; 107*1b3f573fSAndroid Build Coastguard Worker@synthesize fields = fields_; 108*1b3f573fSAndroid Build Coastguard Worker@synthesize oneofs = oneofs_; 109*1b3f573fSAndroid Build Coastguard Worker@synthesize extensionRanges = extensionRanges_; 110*1b3f573fSAndroid Build Coastguard Worker@synthesize extensionRangesCount = extensionRangesCount_; 111*1b3f573fSAndroid Build Coastguard Worker@synthesize file = file_; 112*1b3f573fSAndroid Build Coastguard Worker@synthesize wireFormat = wireFormat_; 113*1b3f573fSAndroid Build Coastguard Worker 114*1b3f573fSAndroid Build Coastguard Worker+ (instancetype) 115*1b3f573fSAndroid Build Coastguard Worker allocDescriptorForClass:(Class)messageClass 116*1b3f573fSAndroid Build Coastguard Worker rootClass:(Class)rootClass 117*1b3f573fSAndroid Build Coastguard Worker file:(GPBFileDescriptor *)file 118*1b3f573fSAndroid Build Coastguard Worker fields:(void *)fieldDescriptions 119*1b3f573fSAndroid Build Coastguard Worker fieldCount:(uint32_t)fieldCount 120*1b3f573fSAndroid Build Coastguard Worker storageSize:(uint32_t)storageSize 121*1b3f573fSAndroid Build Coastguard Worker flags:(GPBDescriptorInitializationFlags)flags { 122*1b3f573fSAndroid Build Coastguard Worker // The rootClass is no longer used, but it is passed in to ensure it 123*1b3f573fSAndroid Build Coastguard Worker // was started up during initialization also. 124*1b3f573fSAndroid Build Coastguard Worker (void)rootClass; 125*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *fields = nil; 126*1b3f573fSAndroid Build Coastguard Worker GPBFileSyntax syntax = file.syntax; 127*1b3f573fSAndroid Build Coastguard Worker BOOL fieldsIncludeDefault = 128*1b3f573fSAndroid Build Coastguard Worker (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; 129*1b3f573fSAndroid Build Coastguard Worker BOOL usesClassRefs = 130*1b3f573fSAndroid Build Coastguard Worker (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0; 131*1b3f573fSAndroid Build Coastguard Worker BOOL proto3OptionalKnown = 132*1b3f573fSAndroid Build Coastguard Worker (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0; 133*1b3f573fSAndroid Build Coastguard Worker 134*1b3f573fSAndroid Build Coastguard Worker void *desc; 135*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < fieldCount; ++i) { 136*1b3f573fSAndroid Build Coastguard Worker if (fields == nil) { 137*1b3f573fSAndroid Build Coastguard Worker fields = [[NSMutableArray alloc] initWithCapacity:fieldCount]; 138*1b3f573fSAndroid Build Coastguard Worker } 139*1b3f573fSAndroid Build Coastguard Worker // Need correctly typed pointer for array indexing below to work. 140*1b3f573fSAndroid Build Coastguard Worker if (fieldsIncludeDefault) { 141*1b3f573fSAndroid Build Coastguard Worker GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions; 142*1b3f573fSAndroid Build Coastguard Worker desc = &(fieldDescWithDefault[i]); 143*1b3f573fSAndroid Build Coastguard Worker } else { 144*1b3f573fSAndroid Build Coastguard Worker GPBMessageFieldDescription *fieldDesc = fieldDescriptions; 145*1b3f573fSAndroid Build Coastguard Worker desc = &(fieldDesc[i]); 146*1b3f573fSAndroid Build Coastguard Worker } 147*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *fieldDescriptor = 148*1b3f573fSAndroid Build Coastguard Worker [[GPBFieldDescriptor alloc] initWithFieldDescription:desc 149*1b3f573fSAndroid Build Coastguard Worker includesDefault:fieldsIncludeDefault 150*1b3f573fSAndroid Build Coastguard Worker usesClassRefs:usesClassRefs 151*1b3f573fSAndroid Build Coastguard Worker proto3OptionalKnown:proto3OptionalKnown 152*1b3f573fSAndroid Build Coastguard Worker syntax:syntax]; 153*1b3f573fSAndroid Build Coastguard Worker [fields addObject:fieldDescriptor]; 154*1b3f573fSAndroid Build Coastguard Worker [fieldDescriptor release]; 155*1b3f573fSAndroid Build Coastguard Worker } 156*1b3f573fSAndroid Build Coastguard Worker 157*1b3f573fSAndroid Build Coastguard Worker BOOL wireFormat = (flags & GPBDescriptorInitializationFlag_WireFormat) != 0; 158*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass 159*1b3f573fSAndroid Build Coastguard Worker file:file 160*1b3f573fSAndroid Build Coastguard Worker fields:fields 161*1b3f573fSAndroid Build Coastguard Worker storageSize:storageSize 162*1b3f573fSAndroid Build Coastguard Worker wireFormat:wireFormat]; 163*1b3f573fSAndroid Build Coastguard Worker [fields release]; 164*1b3f573fSAndroid Build Coastguard Worker return descriptor; 165*1b3f573fSAndroid Build Coastguard Worker} 166*1b3f573fSAndroid Build Coastguard Worker 167*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithClass:(Class)messageClass 168*1b3f573fSAndroid Build Coastguard Worker file:(GPBFileDescriptor *)file 169*1b3f573fSAndroid Build Coastguard Worker fields:(NSArray *)fields 170*1b3f573fSAndroid Build Coastguard Worker storageSize:(uint32_t)storageSize 171*1b3f573fSAndroid Build Coastguard Worker wireFormat:(BOOL)wireFormat { 172*1b3f573fSAndroid Build Coastguard Worker if ((self = [super init])) { 173*1b3f573fSAndroid Build Coastguard Worker messageClass_ = messageClass; 174*1b3f573fSAndroid Build Coastguard Worker file_ = file; 175*1b3f573fSAndroid Build Coastguard Worker fields_ = [fields retain]; 176*1b3f573fSAndroid Build Coastguard Worker storageSize_ = storageSize; 177*1b3f573fSAndroid Build Coastguard Worker wireFormat_ = wireFormat; 178*1b3f573fSAndroid Build Coastguard Worker } 179*1b3f573fSAndroid Build Coastguard Worker return self; 180*1b3f573fSAndroid Build Coastguard Worker} 181*1b3f573fSAndroid Build Coastguard Worker 182*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 183*1b3f573fSAndroid Build Coastguard Worker [fields_ release]; 184*1b3f573fSAndroid Build Coastguard Worker [oneofs_ release]; 185*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 186*1b3f573fSAndroid Build Coastguard Worker} 187*1b3f573fSAndroid Build Coastguard Worker 188*1b3f573fSAndroid Build Coastguard Worker- (void)setupOneofs:(const char **)oneofNames 189*1b3f573fSAndroid Build Coastguard Worker count:(uint32_t)count 190*1b3f573fSAndroid Build Coastguard Worker firstHasIndex:(int32_t)firstHasIndex { 191*1b3f573fSAndroid Build Coastguard Worker NSCAssert(firstHasIndex < 0, @"Should always be <0"); 192*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *oneofs = [[NSMutableArray alloc] initWithCapacity:count]; 193*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) { 194*1b3f573fSAndroid Build Coastguard Worker const char *name = oneofNames[i]; 195*1b3f573fSAndroid Build Coastguard Worker NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_); 196*1b3f573fSAndroid Build Coastguard Worker NSCAssert(fieldsForOneof.count > 0, 197*1b3f573fSAndroid Build Coastguard Worker @"No fields for this oneof? (%s:%d)", name, hasIndex); 198*1b3f573fSAndroid Build Coastguard Worker GPBOneofDescriptor *oneofDescriptor = 199*1b3f573fSAndroid Build Coastguard Worker [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof]; 200*1b3f573fSAndroid Build Coastguard Worker [oneofs addObject:oneofDescriptor]; 201*1b3f573fSAndroid Build Coastguard Worker [oneofDescriptor release]; 202*1b3f573fSAndroid Build Coastguard Worker [fieldsForOneof release]; 203*1b3f573fSAndroid Build Coastguard Worker } 204*1b3f573fSAndroid Build Coastguard Worker oneofs_ = oneofs; 205*1b3f573fSAndroid Build Coastguard Worker} 206*1b3f573fSAndroid Build Coastguard Worker 207*1b3f573fSAndroid Build Coastguard Worker- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo { 208*1b3f573fSAndroid Build Coastguard Worker // Extra info is a compile time option, so skip the work if not needed. 209*1b3f573fSAndroid Build Coastguard Worker if (extraTextFormatInfo) { 210*1b3f573fSAndroid Build Coastguard Worker NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo]; 211*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *fieldDescriptor in fields_) { 212*1b3f573fSAndroid Build Coastguard Worker if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) { 213*1b3f573fSAndroid Build Coastguard Worker objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, 214*1b3f573fSAndroid Build Coastguard Worker extraInfoValue, 215*1b3f573fSAndroid Build Coastguard Worker OBJC_ASSOCIATION_RETAIN_NONATOMIC); 216*1b3f573fSAndroid Build Coastguard Worker } 217*1b3f573fSAndroid Build Coastguard Worker } 218*1b3f573fSAndroid Build Coastguard Worker } 219*1b3f573fSAndroid Build Coastguard Worker} 220*1b3f573fSAndroid Build Coastguard Worker 221*1b3f573fSAndroid Build Coastguard Worker- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count { 222*1b3f573fSAndroid Build Coastguard Worker extensionRanges_ = ranges; 223*1b3f573fSAndroid Build Coastguard Worker extensionRangesCount_ = count; 224*1b3f573fSAndroid Build Coastguard Worker} 225*1b3f573fSAndroid Build Coastguard Worker 226*1b3f573fSAndroid Build Coastguard Worker- (void)setupContainingMessageClass:(Class)messageClass { 227*1b3f573fSAndroid Build Coastguard Worker objc_setAssociatedObject(self, &kParentClassValueKey, 228*1b3f573fSAndroid Build Coastguard Worker messageClass, 229*1b3f573fSAndroid Build Coastguard Worker OBJC_ASSOCIATION_ASSIGN); 230*1b3f573fSAndroid Build Coastguard Worker} 231*1b3f573fSAndroid Build Coastguard Worker 232*1b3f573fSAndroid Build Coastguard Worker- (void)setupContainingMessageClassName:(const char *)msgClassName { 233*1b3f573fSAndroid Build Coastguard Worker // Note: Only fetch the class here, can't send messages to it because 234*1b3f573fSAndroid Build Coastguard Worker // that could cause cycles back to this class within +initialize if 235*1b3f573fSAndroid Build Coastguard Worker // two messages have each other in fields (i.e. - they build a graph). 236*1b3f573fSAndroid Build Coastguard Worker Class clazz = objc_getClass(msgClassName); 237*1b3f573fSAndroid Build Coastguard Worker NSAssert(clazz, @"Class %s not defined", msgClassName); 238*1b3f573fSAndroid Build Coastguard Worker [self setupContainingMessageClass:clazz]; 239*1b3f573fSAndroid Build Coastguard Worker} 240*1b3f573fSAndroid Build Coastguard Worker 241*1b3f573fSAndroid Build Coastguard Worker- (void)setupMessageClassNameSuffix:(NSString *)suffix { 242*1b3f573fSAndroid Build Coastguard Worker if (suffix.length) { 243*1b3f573fSAndroid Build Coastguard Worker objc_setAssociatedObject(self, &kClassNameSuffixKey, 244*1b3f573fSAndroid Build Coastguard Worker suffix, 245*1b3f573fSAndroid Build Coastguard Worker OBJC_ASSOCIATION_RETAIN_NONATOMIC); 246*1b3f573fSAndroid Build Coastguard Worker } 247*1b3f573fSAndroid Build Coastguard Worker} 248*1b3f573fSAndroid Build Coastguard Worker 249*1b3f573fSAndroid Build Coastguard Worker- (NSString *)name { 250*1b3f573fSAndroid Build Coastguard Worker return NSStringFromClass(messageClass_); 251*1b3f573fSAndroid Build Coastguard Worker} 252*1b3f573fSAndroid Build Coastguard Worker 253*1b3f573fSAndroid Build Coastguard Worker- (GPBDescriptor *)containingType { 254*1b3f573fSAndroid Build Coastguard Worker Class parentClass = objc_getAssociatedObject(self, &kParentClassValueKey); 255*1b3f573fSAndroid Build Coastguard Worker return [parentClass descriptor]; 256*1b3f573fSAndroid Build Coastguard Worker} 257*1b3f573fSAndroid Build Coastguard Worker 258*1b3f573fSAndroid Build Coastguard Worker- (NSString *)fullName { 259*1b3f573fSAndroid Build Coastguard Worker NSString *className = NSStringFromClass(self.messageClass); 260*1b3f573fSAndroid Build Coastguard Worker GPBFileDescriptor *file = self.file; 261*1b3f573fSAndroid Build Coastguard Worker NSString *objcPrefix = file.objcPrefix; 262*1b3f573fSAndroid Build Coastguard Worker if (objcPrefix && ![className hasPrefix:objcPrefix]) { 263*1b3f573fSAndroid Build Coastguard Worker NSAssert(0, 264*1b3f573fSAndroid Build Coastguard Worker @"Class didn't have correct prefix? (%@ - %@)", 265*1b3f573fSAndroid Build Coastguard Worker className, objcPrefix); 266*1b3f573fSAndroid Build Coastguard Worker return nil; 267*1b3f573fSAndroid Build Coastguard Worker } 268*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *parent = self.containingType; 269*1b3f573fSAndroid Build Coastguard Worker 270*1b3f573fSAndroid Build Coastguard Worker NSString *name = nil; 271*1b3f573fSAndroid Build Coastguard Worker if (parent) { 272*1b3f573fSAndroid Build Coastguard Worker NSString *parentClassName = NSStringFromClass(parent.messageClass); 273*1b3f573fSAndroid Build Coastguard Worker // The generator will add _Class to avoid reserved words, drop it. 274*1b3f573fSAndroid Build Coastguard Worker NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); 275*1b3f573fSAndroid Build Coastguard Worker if (suffix) { 276*1b3f573fSAndroid Build Coastguard Worker if (![parentClassName hasSuffix:suffix]) { 277*1b3f573fSAndroid Build Coastguard Worker NSAssert(0, 278*1b3f573fSAndroid Build Coastguard Worker @"ParentMessage class didn't have correct suffix? (%@ - %@)", 279*1b3f573fSAndroid Build Coastguard Worker className, suffix); 280*1b3f573fSAndroid Build Coastguard Worker return nil; 281*1b3f573fSAndroid Build Coastguard Worker } 282*1b3f573fSAndroid Build Coastguard Worker parentClassName = 283*1b3f573fSAndroid Build Coastguard Worker [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; 284*1b3f573fSAndroid Build Coastguard Worker } 285*1b3f573fSAndroid Build Coastguard Worker NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; 286*1b3f573fSAndroid Build Coastguard Worker if (![className hasPrefix:parentPrefix]) { 287*1b3f573fSAndroid Build Coastguard Worker NSAssert(0, 288*1b3f573fSAndroid Build Coastguard Worker @"Class didn't have the correct parent name prefix? (%@ - %@)", 289*1b3f573fSAndroid Build Coastguard Worker parentPrefix, className); 290*1b3f573fSAndroid Build Coastguard Worker return nil; 291*1b3f573fSAndroid Build Coastguard Worker } 292*1b3f573fSAndroid Build Coastguard Worker name = [className substringFromIndex:parentPrefix.length]; 293*1b3f573fSAndroid Build Coastguard Worker } else { 294*1b3f573fSAndroid Build Coastguard Worker name = [className substringFromIndex:objcPrefix.length]; 295*1b3f573fSAndroid Build Coastguard Worker } 296*1b3f573fSAndroid Build Coastguard Worker 297*1b3f573fSAndroid Build Coastguard Worker // The generator will add _Class to avoid reserved words, drop it. 298*1b3f573fSAndroid Build Coastguard Worker NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); 299*1b3f573fSAndroid Build Coastguard Worker if (suffix) { 300*1b3f573fSAndroid Build Coastguard Worker if (![name hasSuffix:suffix]) { 301*1b3f573fSAndroid Build Coastguard Worker NSAssert(0, 302*1b3f573fSAndroid Build Coastguard Worker @"Message class didn't have correct suffix? (%@ - %@)", 303*1b3f573fSAndroid Build Coastguard Worker name, suffix); 304*1b3f573fSAndroid Build Coastguard Worker return nil; 305*1b3f573fSAndroid Build Coastguard Worker } 306*1b3f573fSAndroid Build Coastguard Worker name = [name substringToIndex:(name.length - suffix.length)]; 307*1b3f573fSAndroid Build Coastguard Worker } 308*1b3f573fSAndroid Build Coastguard Worker 309*1b3f573fSAndroid Build Coastguard Worker NSString *prefix = (parent != nil ? parent.fullName : file.package); 310*1b3f573fSAndroid Build Coastguard Worker NSString *result; 311*1b3f573fSAndroid Build Coastguard Worker if (prefix.length > 0) { 312*1b3f573fSAndroid Build Coastguard Worker result = [NSString stringWithFormat:@"%@.%@", prefix, name]; 313*1b3f573fSAndroid Build Coastguard Worker } else { 314*1b3f573fSAndroid Build Coastguard Worker result = name; 315*1b3f573fSAndroid Build Coastguard Worker } 316*1b3f573fSAndroid Build Coastguard Worker return result; 317*1b3f573fSAndroid Build Coastguard Worker} 318*1b3f573fSAndroid Build Coastguard Worker 319*1b3f573fSAndroid Build Coastguard Worker- (id)copyWithZone:(NSZone *)zone { 320*1b3f573fSAndroid Build Coastguard Worker#pragma unused(zone) 321*1b3f573fSAndroid Build Coastguard Worker return [self retain]; 322*1b3f573fSAndroid Build Coastguard Worker} 323*1b3f573fSAndroid Build Coastguard Worker 324*1b3f573fSAndroid Build Coastguard Worker- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { 325*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *descriptor in fields_) { 326*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldNumber(descriptor) == fieldNumber) { 327*1b3f573fSAndroid Build Coastguard Worker return descriptor; 328*1b3f573fSAndroid Build Coastguard Worker } 329*1b3f573fSAndroid Build Coastguard Worker } 330*1b3f573fSAndroid Build Coastguard Worker return nil; 331*1b3f573fSAndroid Build Coastguard Worker} 332*1b3f573fSAndroid Build Coastguard Worker 333*1b3f573fSAndroid Build Coastguard Worker- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { 334*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *descriptor in fields_) { 335*1b3f573fSAndroid Build Coastguard Worker if ([descriptor.name isEqual:name]) { 336*1b3f573fSAndroid Build Coastguard Worker return descriptor; 337*1b3f573fSAndroid Build Coastguard Worker } 338*1b3f573fSAndroid Build Coastguard Worker } 339*1b3f573fSAndroid Build Coastguard Worker return nil; 340*1b3f573fSAndroid Build Coastguard Worker} 341*1b3f573fSAndroid Build Coastguard Worker 342*1b3f573fSAndroid Build Coastguard Worker- (GPBOneofDescriptor *)oneofWithName:(NSString *)name { 343*1b3f573fSAndroid Build Coastguard Worker for (GPBOneofDescriptor *descriptor in oneofs_) { 344*1b3f573fSAndroid Build Coastguard Worker if ([descriptor.name isEqual:name]) { 345*1b3f573fSAndroid Build Coastguard Worker return descriptor; 346*1b3f573fSAndroid Build Coastguard Worker } 347*1b3f573fSAndroid Build Coastguard Worker } 348*1b3f573fSAndroid Build Coastguard Worker return nil; 349*1b3f573fSAndroid Build Coastguard Worker} 350*1b3f573fSAndroid Build Coastguard Worker 351*1b3f573fSAndroid Build Coastguard Worker@end 352*1b3f573fSAndroid Build Coastguard Worker 353*1b3f573fSAndroid Build Coastguard Worker@implementation GPBFileDescriptor { 354*1b3f573fSAndroid Build Coastguard Worker NSString *package_; 355*1b3f573fSAndroid Build Coastguard Worker NSString *objcPrefix_; 356*1b3f573fSAndroid Build Coastguard Worker GPBFileSyntax syntax_; 357*1b3f573fSAndroid Build Coastguard Worker} 358*1b3f573fSAndroid Build Coastguard Worker 359*1b3f573fSAndroid Build Coastguard Worker@synthesize package = package_; 360*1b3f573fSAndroid Build Coastguard Worker@synthesize objcPrefix = objcPrefix_; 361*1b3f573fSAndroid Build Coastguard Worker@synthesize syntax = syntax_; 362*1b3f573fSAndroid Build Coastguard Worker 363*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithPackage:(NSString *)package 364*1b3f573fSAndroid Build Coastguard Worker objcPrefix:(NSString *)objcPrefix 365*1b3f573fSAndroid Build Coastguard Worker syntax:(GPBFileSyntax)syntax { 366*1b3f573fSAndroid Build Coastguard Worker self = [super init]; 367*1b3f573fSAndroid Build Coastguard Worker if (self) { 368*1b3f573fSAndroid Build Coastguard Worker package_ = [package copy]; 369*1b3f573fSAndroid Build Coastguard Worker objcPrefix_ = [objcPrefix copy]; 370*1b3f573fSAndroid Build Coastguard Worker syntax_ = syntax; 371*1b3f573fSAndroid Build Coastguard Worker } 372*1b3f573fSAndroid Build Coastguard Worker return self; 373*1b3f573fSAndroid Build Coastguard Worker} 374*1b3f573fSAndroid Build Coastguard Worker 375*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithPackage:(NSString *)package 376*1b3f573fSAndroid Build Coastguard Worker syntax:(GPBFileSyntax)syntax { 377*1b3f573fSAndroid Build Coastguard Worker self = [super init]; 378*1b3f573fSAndroid Build Coastguard Worker if (self) { 379*1b3f573fSAndroid Build Coastguard Worker package_ = [package copy]; 380*1b3f573fSAndroid Build Coastguard Worker syntax_ = syntax; 381*1b3f573fSAndroid Build Coastguard Worker } 382*1b3f573fSAndroid Build Coastguard Worker return self; 383*1b3f573fSAndroid Build Coastguard Worker} 384*1b3f573fSAndroid Build Coastguard Worker 385*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 386*1b3f573fSAndroid Build Coastguard Worker [package_ release]; 387*1b3f573fSAndroid Build Coastguard Worker [objcPrefix_ release]; 388*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 389*1b3f573fSAndroid Build Coastguard Worker} 390*1b3f573fSAndroid Build Coastguard Worker 391*1b3f573fSAndroid Build Coastguard Worker@end 392*1b3f573fSAndroid Build Coastguard Worker 393*1b3f573fSAndroid Build Coastguard Worker@implementation GPBOneofDescriptor 394*1b3f573fSAndroid Build Coastguard Worker 395*1b3f573fSAndroid Build Coastguard Worker@synthesize fields = fields_; 396*1b3f573fSAndroid Build Coastguard Worker 397*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { 398*1b3f573fSAndroid Build Coastguard Worker self = [super init]; 399*1b3f573fSAndroid Build Coastguard Worker if (self) { 400*1b3f573fSAndroid Build Coastguard Worker name_ = name; 401*1b3f573fSAndroid Build Coastguard Worker fields_ = [fields retain]; 402*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *fieldDesc in fields) { 403*1b3f573fSAndroid Build Coastguard Worker fieldDesc->containingOneof_ = self; 404*1b3f573fSAndroid Build Coastguard Worker } 405*1b3f573fSAndroid Build Coastguard Worker 406*1b3f573fSAndroid Build Coastguard Worker caseSel_ = SelFromStrings(NULL, name, "OneOfCase", NO); 407*1b3f573fSAndroid Build Coastguard Worker } 408*1b3f573fSAndroid Build Coastguard Worker return self; 409*1b3f573fSAndroid Build Coastguard Worker} 410*1b3f573fSAndroid Build Coastguard Worker 411*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 412*1b3f573fSAndroid Build Coastguard Worker [fields_ release]; 413*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 414*1b3f573fSAndroid Build Coastguard Worker} 415*1b3f573fSAndroid Build Coastguard Worker 416*1b3f573fSAndroid Build Coastguard Worker- (NSString *)name { 417*1b3f573fSAndroid Build Coastguard Worker return (NSString * _Nonnull)@(name_); 418*1b3f573fSAndroid Build Coastguard Worker} 419*1b3f573fSAndroid Build Coastguard Worker 420*1b3f573fSAndroid Build Coastguard Worker- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { 421*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *descriptor in fields_) { 422*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldNumber(descriptor) == fieldNumber) { 423*1b3f573fSAndroid Build Coastguard Worker return descriptor; 424*1b3f573fSAndroid Build Coastguard Worker } 425*1b3f573fSAndroid Build Coastguard Worker } 426*1b3f573fSAndroid Build Coastguard Worker return nil; 427*1b3f573fSAndroid Build Coastguard Worker} 428*1b3f573fSAndroid Build Coastguard Worker 429*1b3f573fSAndroid Build Coastguard Worker- (GPBFieldDescriptor *)fieldWithName:(NSString *)name { 430*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *descriptor in fields_) { 431*1b3f573fSAndroid Build Coastguard Worker if ([descriptor.name isEqual:name]) { 432*1b3f573fSAndroid Build Coastguard Worker return descriptor; 433*1b3f573fSAndroid Build Coastguard Worker } 434*1b3f573fSAndroid Build Coastguard Worker } 435*1b3f573fSAndroid Build Coastguard Worker return nil; 436*1b3f573fSAndroid Build Coastguard Worker} 437*1b3f573fSAndroid Build Coastguard Worker 438*1b3f573fSAndroid Build Coastguard Worker@end 439*1b3f573fSAndroid Build Coastguard Worker 440*1b3f573fSAndroid Build Coastguard Workeruint32_t GPBFieldTag(GPBFieldDescriptor *self) { 441*1b3f573fSAndroid Build Coastguard Worker GPBMessageFieldDescription *description = self->description_; 442*1b3f573fSAndroid Build Coastguard Worker GPBWireFormat format; 443*1b3f573fSAndroid Build Coastguard Worker if ((description->flags & GPBFieldMapKeyMask) != 0) { 444*1b3f573fSAndroid Build Coastguard Worker // Maps are repeated messages on the wire. 445*1b3f573fSAndroid Build Coastguard Worker format = GPBWireFormatForType(GPBDataTypeMessage, NO); 446*1b3f573fSAndroid Build Coastguard Worker } else { 447*1b3f573fSAndroid Build Coastguard Worker format = GPBWireFormatForType(description->dataType, 448*1b3f573fSAndroid Build Coastguard Worker ((description->flags & GPBFieldPacked) != 0)); 449*1b3f573fSAndroid Build Coastguard Worker } 450*1b3f573fSAndroid Build Coastguard Worker return GPBWireFormatMakeTag(description->number, format); 451*1b3f573fSAndroid Build Coastguard Worker} 452*1b3f573fSAndroid Build Coastguard Worker 453*1b3f573fSAndroid Build Coastguard Workeruint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { 454*1b3f573fSAndroid Build Coastguard Worker GPBMessageFieldDescription *description = self->description_; 455*1b3f573fSAndroid Build Coastguard Worker NSCAssert((description->flags & GPBFieldRepeated) != 0, 456*1b3f573fSAndroid Build Coastguard Worker @"Only valid on repeated fields"); 457*1b3f573fSAndroid Build Coastguard Worker GPBWireFormat format = 458*1b3f573fSAndroid Build Coastguard Worker GPBWireFormatForType(description->dataType, 459*1b3f573fSAndroid Build Coastguard Worker ((description->flags & GPBFieldPacked) == 0)); 460*1b3f573fSAndroid Build Coastguard Worker return GPBWireFormatMakeTag(description->number, format); 461*1b3f573fSAndroid Build Coastguard Worker} 462*1b3f573fSAndroid Build Coastguard Worker 463*1b3f573fSAndroid Build Coastguard Worker@implementation GPBFieldDescriptor { 464*1b3f573fSAndroid Build Coastguard Worker GPBGenericValue defaultValue_; 465*1b3f573fSAndroid Build Coastguard Worker 466*1b3f573fSAndroid Build Coastguard Worker // Message ivars 467*1b3f573fSAndroid Build Coastguard Worker Class msgClass_; 468*1b3f573fSAndroid Build Coastguard Worker 469*1b3f573fSAndroid Build Coastguard Worker // Enum ivars. 470*1b3f573fSAndroid Build Coastguard Worker // If protos are generated with GenerateEnumDescriptors on then it will 471*1b3f573fSAndroid Build Coastguard Worker // be a enumDescriptor, otherwise it will be a enumVerifier. 472*1b3f573fSAndroid Build Coastguard Worker union { 473*1b3f573fSAndroid Build Coastguard Worker GPBEnumDescriptor *enumDescriptor_; 474*1b3f573fSAndroid Build Coastguard Worker GPBEnumValidationFunc enumVerifier_; 475*1b3f573fSAndroid Build Coastguard Worker } enumHandling_; 476*1b3f573fSAndroid Build Coastguard Worker} 477*1b3f573fSAndroid Build Coastguard Worker 478*1b3f573fSAndroid Build Coastguard Worker@synthesize msgClass = msgClass_; 479*1b3f573fSAndroid Build Coastguard Worker@synthesize containingOneof = containingOneof_; 480*1b3f573fSAndroid Build Coastguard Worker 481*1b3f573fSAndroid Build Coastguard Worker- (instancetype)init { 482*1b3f573fSAndroid Build Coastguard Worker // Throw an exception if people attempt to not use the designated initializer. 483*1b3f573fSAndroid Build Coastguard Worker self = [super init]; 484*1b3f573fSAndroid Build Coastguard Worker if (self != nil) { 485*1b3f573fSAndroid Build Coastguard Worker [self doesNotRecognizeSelector:_cmd]; 486*1b3f573fSAndroid Build Coastguard Worker self = nil; 487*1b3f573fSAndroid Build Coastguard Worker } 488*1b3f573fSAndroid Build Coastguard Worker return self; 489*1b3f573fSAndroid Build Coastguard Worker} 490*1b3f573fSAndroid Build Coastguard Worker 491*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithFieldDescription:(void *)description 492*1b3f573fSAndroid Build Coastguard Worker includesDefault:(BOOL)includesDefault 493*1b3f573fSAndroid Build Coastguard Worker usesClassRefs:(BOOL)usesClassRefs 494*1b3f573fSAndroid Build Coastguard Worker proto3OptionalKnown:(BOOL)proto3OptionalKnown 495*1b3f573fSAndroid Build Coastguard Worker syntax:(GPBFileSyntax)syntax { 496*1b3f573fSAndroid Build Coastguard Worker if ((self = [super init])) { 497*1b3f573fSAndroid Build Coastguard Worker GPBMessageFieldDescription *coreDesc; 498*1b3f573fSAndroid Build Coastguard Worker if (includesDefault) { 499*1b3f573fSAndroid Build Coastguard Worker coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core); 500*1b3f573fSAndroid Build Coastguard Worker } else { 501*1b3f573fSAndroid Build Coastguard Worker coreDesc = description; 502*1b3f573fSAndroid Build Coastguard Worker } 503*1b3f573fSAndroid Build Coastguard Worker description_ = coreDesc; 504*1b3f573fSAndroid Build Coastguard Worker getSel_ = sel_getUid(coreDesc->name); 505*1b3f573fSAndroid Build Coastguard Worker setSel_ = SelFromStrings("set", coreDesc->name, NULL, YES); 506*1b3f573fSAndroid Build Coastguard Worker 507*1b3f573fSAndroid Build Coastguard Worker GPBDataType dataType = coreDesc->dataType; 508*1b3f573fSAndroid Build Coastguard Worker BOOL isMessage = GPBDataTypeIsMessage(dataType); 509*1b3f573fSAndroid Build Coastguard Worker BOOL isMapOrArray = GPBFieldIsMapOrArray(self); 510*1b3f573fSAndroid Build Coastguard Worker 511*1b3f573fSAndroid Build Coastguard Worker // If proto3 optionals weren't known (i.e. generated code from an 512*1b3f573fSAndroid Build Coastguard Worker // older version), compute the flag for the rest of the runtime. 513*1b3f573fSAndroid Build Coastguard Worker if (!proto3OptionalKnown) { 514*1b3f573fSAndroid Build Coastguard Worker // If it was... 515*1b3f573fSAndroid Build Coastguard Worker // - proto3 syntax 516*1b3f573fSAndroid Build Coastguard Worker // - not repeated/map 517*1b3f573fSAndroid Build Coastguard Worker // - not in a oneof (negative has index) 518*1b3f573fSAndroid Build Coastguard Worker // - not a message (the flag doesn't make sense for messages) 519*1b3f573fSAndroid Build Coastguard Worker BOOL clearOnZero = ((syntax == GPBFileSyntaxProto3) && 520*1b3f573fSAndroid Build Coastguard Worker !isMapOrArray && 521*1b3f573fSAndroid Build Coastguard Worker (coreDesc->hasIndex >= 0) && 522*1b3f573fSAndroid Build Coastguard Worker !isMessage); 523*1b3f573fSAndroid Build Coastguard Worker if (clearOnZero) { 524*1b3f573fSAndroid Build Coastguard Worker coreDesc->flags |= GPBFieldClearHasIvarOnZero; 525*1b3f573fSAndroid Build Coastguard Worker } 526*1b3f573fSAndroid Build Coastguard Worker } 527*1b3f573fSAndroid Build Coastguard Worker 528*1b3f573fSAndroid Build Coastguard Worker if (isMapOrArray) { 529*1b3f573fSAndroid Build Coastguard Worker // map<>/repeated fields get a *Count property (inplace of a has*) to 530*1b3f573fSAndroid Build Coastguard Worker // support checking if there are any entries without triggering 531*1b3f573fSAndroid Build Coastguard Worker // autocreation. 532*1b3f573fSAndroid Build Coastguard Worker hasOrCountSel_ = SelFromStrings(NULL, coreDesc->name, "_Count", NO); 533*1b3f573fSAndroid Build Coastguard Worker } else { 534*1b3f573fSAndroid Build Coastguard Worker // It is a single field; it gets has/setHas selectors if... 535*1b3f573fSAndroid Build Coastguard Worker // - not in a oneof (negative has index) 536*1b3f573fSAndroid Build Coastguard Worker // - not clearing on zero 537*1b3f573fSAndroid Build Coastguard Worker if ((coreDesc->hasIndex >= 0) && 538*1b3f573fSAndroid Build Coastguard Worker ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) { 539*1b3f573fSAndroid Build Coastguard Worker hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); 540*1b3f573fSAndroid Build Coastguard Worker setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); 541*1b3f573fSAndroid Build Coastguard Worker } 542*1b3f573fSAndroid Build Coastguard Worker } 543*1b3f573fSAndroid Build Coastguard Worker 544*1b3f573fSAndroid Build Coastguard Worker // Extra type specific data. 545*1b3f573fSAndroid Build Coastguard Worker if (isMessage) { 546*1b3f573fSAndroid Build Coastguard Worker // Note: Only fetch the class here, can't send messages to it because 547*1b3f573fSAndroid Build Coastguard Worker // that could cause cycles back to this class within +initialize if 548*1b3f573fSAndroid Build Coastguard Worker // two messages have each other in fields (i.e. - they build a graph). 549*1b3f573fSAndroid Build Coastguard Worker if (usesClassRefs) { 550*1b3f573fSAndroid Build Coastguard Worker msgClass_ = coreDesc->dataTypeSpecific.clazz; 551*1b3f573fSAndroid Build Coastguard Worker } else { 552*1b3f573fSAndroid Build Coastguard Worker // Backwards compatibility for sources generated with older protoc. 553*1b3f573fSAndroid Build Coastguard Worker const char *className = coreDesc->dataTypeSpecific.className; 554*1b3f573fSAndroid Build Coastguard Worker msgClass_ = objc_getClass(className); 555*1b3f573fSAndroid Build Coastguard Worker NSAssert(msgClass_, @"Class %s not defined", className); 556*1b3f573fSAndroid Build Coastguard Worker } 557*1b3f573fSAndroid Build Coastguard Worker } else if (dataType == GPBDataTypeEnum) { 558*1b3f573fSAndroid Build Coastguard Worker if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { 559*1b3f573fSAndroid Build Coastguard Worker enumHandling_.enumDescriptor_ = 560*1b3f573fSAndroid Build Coastguard Worker coreDesc->dataTypeSpecific.enumDescFunc(); 561*1b3f573fSAndroid Build Coastguard Worker } else { 562*1b3f573fSAndroid Build Coastguard Worker enumHandling_.enumVerifier_ = 563*1b3f573fSAndroid Build Coastguard Worker coreDesc->dataTypeSpecific.enumVerifier; 564*1b3f573fSAndroid Build Coastguard Worker } 565*1b3f573fSAndroid Build Coastguard Worker } 566*1b3f573fSAndroid Build Coastguard Worker 567*1b3f573fSAndroid Build Coastguard Worker // Non map<>/repeated fields can have defaults in proto2 syntax. 568*1b3f573fSAndroid Build Coastguard Worker if (!isMapOrArray && includesDefault) { 569*1b3f573fSAndroid Build Coastguard Worker defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; 570*1b3f573fSAndroid Build Coastguard Worker if (dataType == GPBDataTypeBytes) { 571*1b3f573fSAndroid Build Coastguard Worker // Data stored as a length prefixed (network byte order) c-string in 572*1b3f573fSAndroid Build Coastguard Worker // descriptor structure. 573*1b3f573fSAndroid Build Coastguard Worker const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; 574*1b3f573fSAndroid Build Coastguard Worker if (bytes) { 575*1b3f573fSAndroid Build Coastguard Worker uint32_t length; 576*1b3f573fSAndroid Build Coastguard Worker memcpy(&length, bytes, sizeof(length)); 577*1b3f573fSAndroid Build Coastguard Worker length = ntohl(length); 578*1b3f573fSAndroid Build Coastguard Worker bytes += sizeof(length); 579*1b3f573fSAndroid Build Coastguard Worker defaultValue_.valueData = 580*1b3f573fSAndroid Build Coastguard Worker [[NSData alloc] initWithBytes:bytes length:length]; 581*1b3f573fSAndroid Build Coastguard Worker } 582*1b3f573fSAndroid Build Coastguard Worker } 583*1b3f573fSAndroid Build Coastguard Worker } 584*1b3f573fSAndroid Build Coastguard Worker } 585*1b3f573fSAndroid Build Coastguard Worker return self; 586*1b3f573fSAndroid Build Coastguard Worker} 587*1b3f573fSAndroid Build Coastguard Worker 588*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 589*1b3f573fSAndroid Build Coastguard Worker if (description_->dataType == GPBDataTypeBytes && 590*1b3f573fSAndroid Build Coastguard Worker !(description_->flags & GPBFieldRepeated)) { 591*1b3f573fSAndroid Build Coastguard Worker [defaultValue_.valueData release]; 592*1b3f573fSAndroid Build Coastguard Worker } 593*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 594*1b3f573fSAndroid Build Coastguard Worker} 595*1b3f573fSAndroid Build Coastguard Worker 596*1b3f573fSAndroid Build Coastguard Worker- (GPBDataType)dataType { 597*1b3f573fSAndroid Build Coastguard Worker return description_->dataType; 598*1b3f573fSAndroid Build Coastguard Worker} 599*1b3f573fSAndroid Build Coastguard Worker 600*1b3f573fSAndroid Build Coastguard Worker- (BOOL)hasDefaultValue { 601*1b3f573fSAndroid Build Coastguard Worker return (description_->flags & GPBFieldHasDefaultValue) != 0; 602*1b3f573fSAndroid Build Coastguard Worker} 603*1b3f573fSAndroid Build Coastguard Worker 604*1b3f573fSAndroid Build Coastguard Worker- (uint32_t)number { 605*1b3f573fSAndroid Build Coastguard Worker return description_->number; 606*1b3f573fSAndroid Build Coastguard Worker} 607*1b3f573fSAndroid Build Coastguard Worker 608*1b3f573fSAndroid Build Coastguard Worker- (NSString *)name { 609*1b3f573fSAndroid Build Coastguard Worker return (NSString * _Nonnull)@(description_->name); 610*1b3f573fSAndroid Build Coastguard Worker} 611*1b3f573fSAndroid Build Coastguard Worker 612*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isRequired { 613*1b3f573fSAndroid Build Coastguard Worker return (description_->flags & GPBFieldRequired) != 0; 614*1b3f573fSAndroid Build Coastguard Worker} 615*1b3f573fSAndroid Build Coastguard Worker 616*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isOptional { 617*1b3f573fSAndroid Build Coastguard Worker return (description_->flags & GPBFieldOptional) != 0; 618*1b3f573fSAndroid Build Coastguard Worker} 619*1b3f573fSAndroid Build Coastguard Worker 620*1b3f573fSAndroid Build Coastguard Worker- (GPBFieldType)fieldType { 621*1b3f573fSAndroid Build Coastguard Worker GPBFieldFlags flags = description_->flags; 622*1b3f573fSAndroid Build Coastguard Worker if ((flags & GPBFieldRepeated) != 0) { 623*1b3f573fSAndroid Build Coastguard Worker return GPBFieldTypeRepeated; 624*1b3f573fSAndroid Build Coastguard Worker } else if ((flags & GPBFieldMapKeyMask) != 0) { 625*1b3f573fSAndroid Build Coastguard Worker return GPBFieldTypeMap; 626*1b3f573fSAndroid Build Coastguard Worker } else { 627*1b3f573fSAndroid Build Coastguard Worker return GPBFieldTypeSingle; 628*1b3f573fSAndroid Build Coastguard Worker } 629*1b3f573fSAndroid Build Coastguard Worker} 630*1b3f573fSAndroid Build Coastguard Worker 631*1b3f573fSAndroid Build Coastguard Worker- (GPBDataType)mapKeyDataType { 632*1b3f573fSAndroid Build Coastguard Worker switch (description_->flags & GPBFieldMapKeyMask) { 633*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyInt32: 634*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeInt32; 635*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyInt64: 636*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeInt64; 637*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyUInt32: 638*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeUInt32; 639*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyUInt64: 640*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeUInt64; 641*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeySInt32: 642*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeSInt32; 643*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeySInt64: 644*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeSInt64; 645*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyFixed32: 646*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeFixed32; 647*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyFixed64: 648*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeFixed64; 649*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeySFixed32: 650*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeSFixed32; 651*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeySFixed64: 652*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeSFixed64; 653*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyBool: 654*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeBool; 655*1b3f573fSAndroid Build Coastguard Worker case GPBFieldMapKeyString: 656*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeString; 657*1b3f573fSAndroid Build Coastguard Worker 658*1b3f573fSAndroid Build Coastguard Worker default: 659*1b3f573fSAndroid Build Coastguard Worker NSAssert(0, @"Not a map type"); 660*1b3f573fSAndroid Build Coastguard Worker return GPBDataTypeInt32; // For lack of anything better. 661*1b3f573fSAndroid Build Coastguard Worker } 662*1b3f573fSAndroid Build Coastguard Worker} 663*1b3f573fSAndroid Build Coastguard Worker 664*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isPackable { 665*1b3f573fSAndroid Build Coastguard Worker return (description_->flags & GPBFieldPacked) != 0; 666*1b3f573fSAndroid Build Coastguard Worker} 667*1b3f573fSAndroid Build Coastguard Worker 668*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isValidEnumValue:(int32_t)value { 669*1b3f573fSAndroid Build Coastguard Worker NSAssert(description_->dataType == GPBDataTypeEnum, 670*1b3f573fSAndroid Build Coastguard Worker @"Field Must be of type GPBDataTypeEnum"); 671*1b3f573fSAndroid Build Coastguard Worker if (description_->flags & GPBFieldHasEnumDescriptor) { 672*1b3f573fSAndroid Build Coastguard Worker return enumHandling_.enumDescriptor_.enumVerifier(value); 673*1b3f573fSAndroid Build Coastguard Worker } else { 674*1b3f573fSAndroid Build Coastguard Worker return enumHandling_.enumVerifier_(value); 675*1b3f573fSAndroid Build Coastguard Worker } 676*1b3f573fSAndroid Build Coastguard Worker} 677*1b3f573fSAndroid Build Coastguard Worker 678*1b3f573fSAndroid Build Coastguard Worker- (GPBEnumDescriptor *)enumDescriptor { 679*1b3f573fSAndroid Build Coastguard Worker if (description_->flags & GPBFieldHasEnumDescriptor) { 680*1b3f573fSAndroid Build Coastguard Worker return enumHandling_.enumDescriptor_; 681*1b3f573fSAndroid Build Coastguard Worker } else { 682*1b3f573fSAndroid Build Coastguard Worker return nil; 683*1b3f573fSAndroid Build Coastguard Worker } 684*1b3f573fSAndroid Build Coastguard Worker} 685*1b3f573fSAndroid Build Coastguard Worker 686*1b3f573fSAndroid Build Coastguard Worker- (GPBGenericValue)defaultValue { 687*1b3f573fSAndroid Build Coastguard Worker // Depends on the fact that defaultValue_ is initialized either to "0/nil" or 688*1b3f573fSAndroid Build Coastguard Worker // to an actual defaultValue in our initializer. 689*1b3f573fSAndroid Build Coastguard Worker GPBGenericValue value = defaultValue_; 690*1b3f573fSAndroid Build Coastguard Worker 691*1b3f573fSAndroid Build Coastguard Worker if (!(description_->flags & GPBFieldRepeated)) { 692*1b3f573fSAndroid Build Coastguard Worker // We special handle data and strings. If they are nil, we replace them 693*1b3f573fSAndroid Build Coastguard Worker // with empty string/empty data. 694*1b3f573fSAndroid Build Coastguard Worker GPBDataType type = description_->dataType; 695*1b3f573fSAndroid Build Coastguard Worker if (type == GPBDataTypeBytes && value.valueData == nil) { 696*1b3f573fSAndroid Build Coastguard Worker value.valueData = GPBEmptyNSData(); 697*1b3f573fSAndroid Build Coastguard Worker } else if (type == GPBDataTypeString && value.valueString == nil) { 698*1b3f573fSAndroid Build Coastguard Worker value.valueString = @""; 699*1b3f573fSAndroid Build Coastguard Worker } 700*1b3f573fSAndroid Build Coastguard Worker } 701*1b3f573fSAndroid Build Coastguard Worker return value; 702*1b3f573fSAndroid Build Coastguard Worker} 703*1b3f573fSAndroid Build Coastguard Worker 704*1b3f573fSAndroid Build Coastguard Worker- (NSString *)textFormatName { 705*1b3f573fSAndroid Build Coastguard Worker if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) { 706*1b3f573fSAndroid Build Coastguard Worker NSValue *extraInfoValue = 707*1b3f573fSAndroid Build Coastguard Worker objc_getAssociatedObject(self, &kTextFormatExtraValueKey); 708*1b3f573fSAndroid Build Coastguard Worker // Support can be left out at generation time. 709*1b3f573fSAndroid Build Coastguard Worker if (!extraInfoValue) { 710*1b3f573fSAndroid Build Coastguard Worker return nil; 711*1b3f573fSAndroid Build Coastguard Worker } 712*1b3f573fSAndroid Build Coastguard Worker const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue]; 713*1b3f573fSAndroid Build Coastguard Worker return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), 714*1b3f573fSAndroid Build Coastguard Worker self.name); 715*1b3f573fSAndroid Build Coastguard Worker } 716*1b3f573fSAndroid Build Coastguard Worker 717*1b3f573fSAndroid Build Coastguard Worker // The logic here has to match SetCommonFieldVariables() from 718*1b3f573fSAndroid Build Coastguard Worker // objectivec_field.cc in the proto compiler. 719*1b3f573fSAndroid Build Coastguard Worker NSString *name = self.name; 720*1b3f573fSAndroid Build Coastguard Worker NSUInteger len = [name length]; 721*1b3f573fSAndroid Build Coastguard Worker 722*1b3f573fSAndroid Build Coastguard Worker // Remove the "_p" added to reserved names. 723*1b3f573fSAndroid Build Coastguard Worker if ([name hasSuffix:@"_p"]) { 724*1b3f573fSAndroid Build Coastguard Worker name = [name substringToIndex:(len - 2)]; 725*1b3f573fSAndroid Build Coastguard Worker len = [name length]; 726*1b3f573fSAndroid Build Coastguard Worker } 727*1b3f573fSAndroid Build Coastguard Worker 728*1b3f573fSAndroid Build Coastguard Worker // Remove "Array" from the end for repeated fields. 729*1b3f573fSAndroid Build Coastguard Worker if (((description_->flags & GPBFieldRepeated) != 0) && 730*1b3f573fSAndroid Build Coastguard Worker [name hasSuffix:@"Array"]) { 731*1b3f573fSAndroid Build Coastguard Worker name = [name substringToIndex:(len - 5)]; 732*1b3f573fSAndroid Build Coastguard Worker len = [name length]; 733*1b3f573fSAndroid Build Coastguard Worker } 734*1b3f573fSAndroid Build Coastguard Worker 735*1b3f573fSAndroid Build Coastguard Worker // Groups vs. other fields. 736*1b3f573fSAndroid Build Coastguard Worker if (description_->dataType == GPBDataTypeGroup) { 737*1b3f573fSAndroid Build Coastguard Worker // Just capitalize the first letter. 738*1b3f573fSAndroid Build Coastguard Worker unichar firstChar = [name characterAtIndex:0]; 739*1b3f573fSAndroid Build Coastguard Worker if (firstChar >= 'a' && firstChar <= 'z') { 740*1b3f573fSAndroid Build Coastguard Worker NSString *firstCharString = 741*1b3f573fSAndroid Build Coastguard Worker [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')]; 742*1b3f573fSAndroid Build Coastguard Worker NSString *result = 743*1b3f573fSAndroid Build Coastguard Worker [name stringByReplacingCharactersInRange:NSMakeRange(0, 1) 744*1b3f573fSAndroid Build Coastguard Worker withString:firstCharString]; 745*1b3f573fSAndroid Build Coastguard Worker return result; 746*1b3f573fSAndroid Build Coastguard Worker } 747*1b3f573fSAndroid Build Coastguard Worker return name; 748*1b3f573fSAndroid Build Coastguard Worker 749*1b3f573fSAndroid Build Coastguard Worker } else { 750*1b3f573fSAndroid Build Coastguard Worker // Undo the CamelCase. 751*1b3f573fSAndroid Build Coastguard Worker NSMutableString *result = [NSMutableString stringWithCapacity:len]; 752*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < len; i++) { 753*1b3f573fSAndroid Build Coastguard Worker unichar c = [name characterAtIndex:i]; 754*1b3f573fSAndroid Build Coastguard Worker if (c >= 'A' && c <= 'Z') { 755*1b3f573fSAndroid Build Coastguard Worker if (i > 0) { 756*1b3f573fSAndroid Build Coastguard Worker [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')]; 757*1b3f573fSAndroid Build Coastguard Worker } else { 758*1b3f573fSAndroid Build Coastguard Worker [result appendFormat:@"%C", c]; 759*1b3f573fSAndroid Build Coastguard Worker } 760*1b3f573fSAndroid Build Coastguard Worker } else { 761*1b3f573fSAndroid Build Coastguard Worker [result appendFormat:@"%C", c]; 762*1b3f573fSAndroid Build Coastguard Worker } 763*1b3f573fSAndroid Build Coastguard Worker } 764*1b3f573fSAndroid Build Coastguard Worker return result; 765*1b3f573fSAndroid Build Coastguard Worker } 766*1b3f573fSAndroid Build Coastguard Worker} 767*1b3f573fSAndroid Build Coastguard Worker 768*1b3f573fSAndroid Build Coastguard Worker@end 769*1b3f573fSAndroid Build Coastguard Worker 770*1b3f573fSAndroid Build Coastguard Worker@implementation GPBEnumDescriptor { 771*1b3f573fSAndroid Build Coastguard Worker NSString *name_; 772*1b3f573fSAndroid Build Coastguard Worker // valueNames_ is a single c string with all of the value names appended 773*1b3f573fSAndroid Build Coastguard Worker // together, each null terminated. -calcValueNameOffsets fills in 774*1b3f573fSAndroid Build Coastguard Worker // nameOffsets_ with the offsets to allow quicker access to the individual 775*1b3f573fSAndroid Build Coastguard Worker // names. 776*1b3f573fSAndroid Build Coastguard Worker const char *valueNames_; 777*1b3f573fSAndroid Build Coastguard Worker const int32_t *values_; 778*1b3f573fSAndroid Build Coastguard Worker GPBEnumValidationFunc enumVerifier_; 779*1b3f573fSAndroid Build Coastguard Worker const uint8_t *extraTextFormatInfo_; 780*1b3f573fSAndroid Build Coastguard Worker uint32_t *nameOffsets_; 781*1b3f573fSAndroid Build Coastguard Worker uint32_t valueCount_; 782*1b3f573fSAndroid Build Coastguard Worker} 783*1b3f573fSAndroid Build Coastguard Worker 784*1b3f573fSAndroid Build Coastguard Worker@synthesize name = name_; 785*1b3f573fSAndroid Build Coastguard Worker@synthesize enumVerifier = enumVerifier_; 786*1b3f573fSAndroid Build Coastguard Worker 787*1b3f573fSAndroid Build Coastguard Worker+ (instancetype) 788*1b3f573fSAndroid Build Coastguard Worker allocDescriptorForName:(NSString *)name 789*1b3f573fSAndroid Build Coastguard Worker valueNames:(const char *)valueNames 790*1b3f573fSAndroid Build Coastguard Worker values:(const int32_t *)values 791*1b3f573fSAndroid Build Coastguard Worker count:(uint32_t)valueCount 792*1b3f573fSAndroid Build Coastguard Worker enumVerifier:(GPBEnumValidationFunc)enumVerifier { 793*1b3f573fSAndroid Build Coastguard Worker GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name 794*1b3f573fSAndroid Build Coastguard Worker valueNames:valueNames 795*1b3f573fSAndroid Build Coastguard Worker values:values 796*1b3f573fSAndroid Build Coastguard Worker count:valueCount 797*1b3f573fSAndroid Build Coastguard Worker enumVerifier:enumVerifier]; 798*1b3f573fSAndroid Build Coastguard Worker return descriptor; 799*1b3f573fSAndroid Build Coastguard Worker} 800*1b3f573fSAndroid Build Coastguard Worker 801*1b3f573fSAndroid Build Coastguard Worker+ (instancetype) 802*1b3f573fSAndroid Build Coastguard Worker allocDescriptorForName:(NSString *)name 803*1b3f573fSAndroid Build Coastguard Worker valueNames:(const char *)valueNames 804*1b3f573fSAndroid Build Coastguard Worker values:(const int32_t *)values 805*1b3f573fSAndroid Build Coastguard Worker count:(uint32_t)valueCount 806*1b3f573fSAndroid Build Coastguard Worker enumVerifier:(GPBEnumValidationFunc)enumVerifier 807*1b3f573fSAndroid Build Coastguard Worker extraTextFormatInfo:(const char *)extraTextFormatInfo { 808*1b3f573fSAndroid Build Coastguard Worker // Call the common case. 809*1b3f573fSAndroid Build Coastguard Worker GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name 810*1b3f573fSAndroid Build Coastguard Worker valueNames:valueNames 811*1b3f573fSAndroid Build Coastguard Worker values:values 812*1b3f573fSAndroid Build Coastguard Worker count:valueCount 813*1b3f573fSAndroid Build Coastguard Worker enumVerifier:enumVerifier]; 814*1b3f573fSAndroid Build Coastguard Worker // Set the extra info. 815*1b3f573fSAndroid Build Coastguard Worker descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo; 816*1b3f573fSAndroid Build Coastguard Worker return descriptor; 817*1b3f573fSAndroid Build Coastguard Worker} 818*1b3f573fSAndroid Build Coastguard Worker 819*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithName:(NSString *)name 820*1b3f573fSAndroid Build Coastguard Worker valueNames:(const char *)valueNames 821*1b3f573fSAndroid Build Coastguard Worker values:(const int32_t *)values 822*1b3f573fSAndroid Build Coastguard Worker count:(uint32_t)valueCount 823*1b3f573fSAndroid Build Coastguard Worker enumVerifier:(GPBEnumValidationFunc)enumVerifier { 824*1b3f573fSAndroid Build Coastguard Worker if ((self = [super init])) { 825*1b3f573fSAndroid Build Coastguard Worker name_ = [name copy]; 826*1b3f573fSAndroid Build Coastguard Worker valueNames_ = valueNames; 827*1b3f573fSAndroid Build Coastguard Worker values_ = values; 828*1b3f573fSAndroid Build Coastguard Worker valueCount_ = valueCount; 829*1b3f573fSAndroid Build Coastguard Worker enumVerifier_ = enumVerifier; 830*1b3f573fSAndroid Build Coastguard Worker } 831*1b3f573fSAndroid Build Coastguard Worker return self; 832*1b3f573fSAndroid Build Coastguard Worker} 833*1b3f573fSAndroid Build Coastguard Worker 834*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 835*1b3f573fSAndroid Build Coastguard Worker [name_ release]; 836*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_) free(nameOffsets_); 837*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 838*1b3f573fSAndroid Build Coastguard Worker} 839*1b3f573fSAndroid Build Coastguard Worker 840*1b3f573fSAndroid Build Coastguard Worker- (void)calcValueNameOffsets { 841*1b3f573fSAndroid Build Coastguard Worker @synchronized(self) { 842*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ != NULL) { 843*1b3f573fSAndroid Build Coastguard Worker return; 844*1b3f573fSAndroid Build Coastguard Worker } 845*1b3f573fSAndroid Build Coastguard Worker uint32_t *offsets = malloc(valueCount_ * sizeof(uint32_t)); 846*1b3f573fSAndroid Build Coastguard Worker if (!offsets) return; 847*1b3f573fSAndroid Build Coastguard Worker const char *scan = valueNames_; 848*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < valueCount_; ++i) { 849*1b3f573fSAndroid Build Coastguard Worker offsets[i] = (uint32_t)(scan - valueNames_); 850*1b3f573fSAndroid Build Coastguard Worker while (*scan != '\0') ++scan; 851*1b3f573fSAndroid Build Coastguard Worker ++scan; // Step over the null. 852*1b3f573fSAndroid Build Coastguard Worker } 853*1b3f573fSAndroid Build Coastguard Worker nameOffsets_ = offsets; 854*1b3f573fSAndroid Build Coastguard Worker } 855*1b3f573fSAndroid Build Coastguard Worker} 856*1b3f573fSAndroid Build Coastguard Worker 857*1b3f573fSAndroid Build Coastguard Worker- (NSString *)enumNameForValue:(int32_t)number { 858*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < valueCount_; ++i) { 859*1b3f573fSAndroid Build Coastguard Worker if (values_[i] == number) { 860*1b3f573fSAndroid Build Coastguard Worker return [self getEnumNameForIndex:i]; 861*1b3f573fSAndroid Build Coastguard Worker } 862*1b3f573fSAndroid Build Coastguard Worker } 863*1b3f573fSAndroid Build Coastguard Worker return nil; 864*1b3f573fSAndroid Build Coastguard Worker} 865*1b3f573fSAndroid Build Coastguard Worker 866*1b3f573fSAndroid Build Coastguard Worker- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name { 867*1b3f573fSAndroid Build Coastguard Worker // Must have the prefix. 868*1b3f573fSAndroid Build Coastguard Worker NSUInteger prefixLen = name_.length + 1; 869*1b3f573fSAndroid Build Coastguard Worker if ((name.length <= prefixLen) || ![name hasPrefix:name_] || 870*1b3f573fSAndroid Build Coastguard Worker ([name characterAtIndex:prefixLen - 1] != '_')) { 871*1b3f573fSAndroid Build Coastguard Worker return NO; 872*1b3f573fSAndroid Build Coastguard Worker } 873*1b3f573fSAndroid Build Coastguard Worker 874*1b3f573fSAndroid Build Coastguard Worker // Skip over the prefix. 875*1b3f573fSAndroid Build Coastguard Worker const char *nameAsCStr = [name UTF8String]; 876*1b3f573fSAndroid Build Coastguard Worker nameAsCStr += prefixLen; 877*1b3f573fSAndroid Build Coastguard Worker 878*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) [self calcValueNameOffsets]; 879*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) return NO; 880*1b3f573fSAndroid Build Coastguard Worker 881*1b3f573fSAndroid Build Coastguard Worker // Find it. 882*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < valueCount_; ++i) { 883*1b3f573fSAndroid Build Coastguard Worker const char *valueName = valueNames_ + nameOffsets_[i]; 884*1b3f573fSAndroid Build Coastguard Worker if (strcmp(nameAsCStr, valueName) == 0) { 885*1b3f573fSAndroid Build Coastguard Worker if (outValue) { 886*1b3f573fSAndroid Build Coastguard Worker *outValue = values_[i]; 887*1b3f573fSAndroid Build Coastguard Worker } 888*1b3f573fSAndroid Build Coastguard Worker return YES; 889*1b3f573fSAndroid Build Coastguard Worker } 890*1b3f573fSAndroid Build Coastguard Worker } 891*1b3f573fSAndroid Build Coastguard Worker return NO; 892*1b3f573fSAndroid Build Coastguard Worker} 893*1b3f573fSAndroid Build Coastguard Worker 894*1b3f573fSAndroid Build Coastguard Worker- (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName { 895*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) [self calcValueNameOffsets]; 896*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) return NO; 897*1b3f573fSAndroid Build Coastguard Worker 898*1b3f573fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < valueCount_; ++i) { 899*1b3f573fSAndroid Build Coastguard Worker NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i]; 900*1b3f573fSAndroid Build Coastguard Worker if ([valueTextFormatName isEqual:textFormatName]) { 901*1b3f573fSAndroid Build Coastguard Worker if (outValue) { 902*1b3f573fSAndroid Build Coastguard Worker *outValue = values_[i]; 903*1b3f573fSAndroid Build Coastguard Worker } 904*1b3f573fSAndroid Build Coastguard Worker return YES; 905*1b3f573fSAndroid Build Coastguard Worker } 906*1b3f573fSAndroid Build Coastguard Worker } 907*1b3f573fSAndroid Build Coastguard Worker return NO; 908*1b3f573fSAndroid Build Coastguard Worker} 909*1b3f573fSAndroid Build Coastguard Worker 910*1b3f573fSAndroid Build Coastguard Worker- (NSString *)textFormatNameForValue:(int32_t)number { 911*1b3f573fSAndroid Build Coastguard Worker // Find the EnumValue descriptor and its index. 912*1b3f573fSAndroid Build Coastguard Worker BOOL foundIt = NO; 913*1b3f573fSAndroid Build Coastguard Worker uint32_t valueDescriptorIndex; 914*1b3f573fSAndroid Build Coastguard Worker for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; 915*1b3f573fSAndroid Build Coastguard Worker ++valueDescriptorIndex) { 916*1b3f573fSAndroid Build Coastguard Worker if (values_[valueDescriptorIndex] == number) { 917*1b3f573fSAndroid Build Coastguard Worker foundIt = YES; 918*1b3f573fSAndroid Build Coastguard Worker break; 919*1b3f573fSAndroid Build Coastguard Worker } 920*1b3f573fSAndroid Build Coastguard Worker } 921*1b3f573fSAndroid Build Coastguard Worker 922*1b3f573fSAndroid Build Coastguard Worker if (!foundIt) { 923*1b3f573fSAndroid Build Coastguard Worker return nil; 924*1b3f573fSAndroid Build Coastguard Worker } 925*1b3f573fSAndroid Build Coastguard Worker return [self getEnumTextFormatNameForIndex:valueDescriptorIndex]; 926*1b3f573fSAndroid Build Coastguard Worker} 927*1b3f573fSAndroid Build Coastguard Worker 928*1b3f573fSAndroid Build Coastguard Worker- (uint32_t)enumNameCount { 929*1b3f573fSAndroid Build Coastguard Worker return valueCount_; 930*1b3f573fSAndroid Build Coastguard Worker} 931*1b3f573fSAndroid Build Coastguard Worker 932*1b3f573fSAndroid Build Coastguard Worker- (NSString *)getEnumNameForIndex:(uint32_t)index { 933*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) [self calcValueNameOffsets]; 934*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) return nil; 935*1b3f573fSAndroid Build Coastguard Worker 936*1b3f573fSAndroid Build Coastguard Worker if (index >= valueCount_) { 937*1b3f573fSAndroid Build Coastguard Worker return nil; 938*1b3f573fSAndroid Build Coastguard Worker } 939*1b3f573fSAndroid Build Coastguard Worker const char *valueName = valueNames_ + nameOffsets_[index]; 940*1b3f573fSAndroid Build Coastguard Worker NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName]; 941*1b3f573fSAndroid Build Coastguard Worker return fullName; 942*1b3f573fSAndroid Build Coastguard Worker} 943*1b3f573fSAndroid Build Coastguard Worker 944*1b3f573fSAndroid Build Coastguard Worker- (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index { 945*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) [self calcValueNameOffsets]; 946*1b3f573fSAndroid Build Coastguard Worker if (nameOffsets_ == NULL) return nil; 947*1b3f573fSAndroid Build Coastguard Worker 948*1b3f573fSAndroid Build Coastguard Worker if (index >= valueCount_) { 949*1b3f573fSAndroid Build Coastguard Worker return nil; 950*1b3f573fSAndroid Build Coastguard Worker } 951*1b3f573fSAndroid Build Coastguard Worker NSString *result = nil; 952*1b3f573fSAndroid Build Coastguard Worker // Naming adds an underscore between enum name and value name, skip that also. 953*1b3f573fSAndroid Build Coastguard Worker const char *valueName = valueNames_ + nameOffsets_[index]; 954*1b3f573fSAndroid Build Coastguard Worker NSString *shortName = @(valueName); 955*1b3f573fSAndroid Build Coastguard Worker 956*1b3f573fSAndroid Build Coastguard Worker // See if it is in the map of special format handling. 957*1b3f573fSAndroid Build Coastguard Worker if (extraTextFormatInfo_) { 958*1b3f573fSAndroid Build Coastguard Worker result = GPBDecodeTextFormatName(extraTextFormatInfo_, 959*1b3f573fSAndroid Build Coastguard Worker (int32_t)index, shortName); 960*1b3f573fSAndroid Build Coastguard Worker } 961*1b3f573fSAndroid Build Coastguard Worker // Logic here needs to match what objectivec_enum.cc does in the proto 962*1b3f573fSAndroid Build Coastguard Worker // compiler. 963*1b3f573fSAndroid Build Coastguard Worker if (result == nil) { 964*1b3f573fSAndroid Build Coastguard Worker NSUInteger len = [shortName length]; 965*1b3f573fSAndroid Build Coastguard Worker NSMutableString *worker = [NSMutableString stringWithCapacity:len]; 966*1b3f573fSAndroid Build Coastguard Worker for (NSUInteger i = 0; i < len; i++) { 967*1b3f573fSAndroid Build Coastguard Worker unichar c = [shortName characterAtIndex:i]; 968*1b3f573fSAndroid Build Coastguard Worker if (i > 0 && c >= 'A' && c <= 'Z') { 969*1b3f573fSAndroid Build Coastguard Worker [worker appendString:@"_"]; 970*1b3f573fSAndroid Build Coastguard Worker } 971*1b3f573fSAndroid Build Coastguard Worker [worker appendFormat:@"%c", toupper((char)c)]; 972*1b3f573fSAndroid Build Coastguard Worker } 973*1b3f573fSAndroid Build Coastguard Worker result = worker; 974*1b3f573fSAndroid Build Coastguard Worker } 975*1b3f573fSAndroid Build Coastguard Worker return result; 976*1b3f573fSAndroid Build Coastguard Worker} 977*1b3f573fSAndroid Build Coastguard Worker 978*1b3f573fSAndroid Build Coastguard Worker@end 979*1b3f573fSAndroid Build Coastguard Worker 980*1b3f573fSAndroid Build Coastguard Worker@implementation GPBExtensionDescriptor { 981*1b3f573fSAndroid Build Coastguard Worker GPBGenericValue defaultValue_; 982*1b3f573fSAndroid Build Coastguard Worker} 983*1b3f573fSAndroid Build Coastguard Worker 984*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc 985*1b3f573fSAndroid Build Coastguard Worker usesClassRefs:(BOOL)usesClassRefs { 986*1b3f573fSAndroid Build Coastguard Worker if ((self = [super init])) { 987*1b3f573fSAndroid Build Coastguard Worker description_ = desc; 988*1b3f573fSAndroid Build Coastguard Worker if (!usesClassRefs) { 989*1b3f573fSAndroid Build Coastguard Worker // Legacy without class ref support. 990*1b3f573fSAndroid Build Coastguard Worker const char *className = description_->messageOrGroupClass.name; 991*1b3f573fSAndroid Build Coastguard Worker if (className) { 992*1b3f573fSAndroid Build Coastguard Worker Class clazz = objc_lookUpClass(className); 993*1b3f573fSAndroid Build Coastguard Worker NSAssert(clazz != Nil, @"Class %s not defined", className); 994*1b3f573fSAndroid Build Coastguard Worker description_->messageOrGroupClass.clazz = clazz; 995*1b3f573fSAndroid Build Coastguard Worker } 996*1b3f573fSAndroid Build Coastguard Worker 997*1b3f573fSAndroid Build Coastguard Worker const char *extendedClassName = description_->extendedClass.name; 998*1b3f573fSAndroid Build Coastguard Worker if (extendedClassName) { 999*1b3f573fSAndroid Build Coastguard Worker Class clazz = objc_lookUpClass(extendedClassName); 1000*1b3f573fSAndroid Build Coastguard Worker NSAssert(clazz, @"Class %s not defined", extendedClassName); 1001*1b3f573fSAndroid Build Coastguard Worker description_->extendedClass.clazz = clazz; 1002*1b3f573fSAndroid Build Coastguard Worker } 1003*1b3f573fSAndroid Build Coastguard Worker } 1004*1b3f573fSAndroid Build Coastguard Worker 1005*1b3f573fSAndroid Build Coastguard Worker GPBDataType type = description_->dataType; 1006*1b3f573fSAndroid Build Coastguard Worker if (type == GPBDataTypeBytes) { 1007*1b3f573fSAndroid Build Coastguard Worker // Data stored as a length prefixed c-string in descriptor records. 1008*1b3f573fSAndroid Build Coastguard Worker const uint8_t *bytes = 1009*1b3f573fSAndroid Build Coastguard Worker (const uint8_t *)description_->defaultValue.valueData; 1010*1b3f573fSAndroid Build Coastguard Worker if (bytes) { 1011*1b3f573fSAndroid Build Coastguard Worker uint32_t length; 1012*1b3f573fSAndroid Build Coastguard Worker memcpy(&length, bytes, sizeof(length)); 1013*1b3f573fSAndroid Build Coastguard Worker // The length is stored in network byte order. 1014*1b3f573fSAndroid Build Coastguard Worker length = ntohl(length); 1015*1b3f573fSAndroid Build Coastguard Worker bytes += sizeof(length); 1016*1b3f573fSAndroid Build Coastguard Worker defaultValue_.valueData = 1017*1b3f573fSAndroid Build Coastguard Worker [[NSData alloc] initWithBytes:bytes length:length]; 1018*1b3f573fSAndroid Build Coastguard Worker } 1019*1b3f573fSAndroid Build Coastguard Worker } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) { 1020*1b3f573fSAndroid Build Coastguard Worker // The default is looked up in -defaultValue instead since extensions 1021*1b3f573fSAndroid Build Coastguard Worker // aren't common, we avoid the hit startup hit and it avoid initialization 1022*1b3f573fSAndroid Build Coastguard Worker // order issues. 1023*1b3f573fSAndroid Build Coastguard Worker } else { 1024*1b3f573fSAndroid Build Coastguard Worker defaultValue_ = description_->defaultValue; 1025*1b3f573fSAndroid Build Coastguard Worker } 1026*1b3f573fSAndroid Build Coastguard Worker } 1027*1b3f573fSAndroid Build Coastguard Worker return self; 1028*1b3f573fSAndroid Build Coastguard Worker} 1029*1b3f573fSAndroid Build Coastguard Worker 1030*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc { 1031*1b3f573fSAndroid Build Coastguard Worker return [self initWithExtensionDescription:desc usesClassRefs:NO]; 1032*1b3f573fSAndroid Build Coastguard Worker} 1033*1b3f573fSAndroid Build Coastguard Worker 1034*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 1035*1b3f573fSAndroid Build Coastguard Worker if ((description_->dataType == GPBDataTypeBytes) && 1036*1b3f573fSAndroid Build Coastguard Worker !GPBExtensionIsRepeated(description_)) { 1037*1b3f573fSAndroid Build Coastguard Worker [defaultValue_.valueData release]; 1038*1b3f573fSAndroid Build Coastguard Worker } 1039*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 1040*1b3f573fSAndroid Build Coastguard Worker} 1041*1b3f573fSAndroid Build Coastguard Worker 1042*1b3f573fSAndroid Build Coastguard Worker- (instancetype)copyWithZone:(NSZone *)zone { 1043*1b3f573fSAndroid Build Coastguard Worker#pragma unused(zone) 1044*1b3f573fSAndroid Build Coastguard Worker // Immutable. 1045*1b3f573fSAndroid Build Coastguard Worker return [self retain]; 1046*1b3f573fSAndroid Build Coastguard Worker} 1047*1b3f573fSAndroid Build Coastguard Worker 1048*1b3f573fSAndroid Build Coastguard Worker- (NSString *)singletonName { 1049*1b3f573fSAndroid Build Coastguard Worker return (NSString * _Nonnull)@(description_->singletonName); 1050*1b3f573fSAndroid Build Coastguard Worker} 1051*1b3f573fSAndroid Build Coastguard Worker 1052*1b3f573fSAndroid Build Coastguard Worker- (const char *)singletonNameC { 1053*1b3f573fSAndroid Build Coastguard Worker return description_->singletonName; 1054*1b3f573fSAndroid Build Coastguard Worker} 1055*1b3f573fSAndroid Build Coastguard Worker 1056*1b3f573fSAndroid Build Coastguard Worker- (uint32_t)fieldNumber { 1057*1b3f573fSAndroid Build Coastguard Worker return description_->fieldNumber; 1058*1b3f573fSAndroid Build Coastguard Worker} 1059*1b3f573fSAndroid Build Coastguard Worker 1060*1b3f573fSAndroid Build Coastguard Worker- (GPBDataType)dataType { 1061*1b3f573fSAndroid Build Coastguard Worker return description_->dataType; 1062*1b3f573fSAndroid Build Coastguard Worker} 1063*1b3f573fSAndroid Build Coastguard Worker 1064*1b3f573fSAndroid Build Coastguard Worker- (GPBWireFormat)wireType { 1065*1b3f573fSAndroid Build Coastguard Worker return GPBWireFormatForType(description_->dataType, 1066*1b3f573fSAndroid Build Coastguard Worker GPBExtensionIsPacked(description_)); 1067*1b3f573fSAndroid Build Coastguard Worker} 1068*1b3f573fSAndroid Build Coastguard Worker 1069*1b3f573fSAndroid Build Coastguard Worker- (GPBWireFormat)alternateWireType { 1070*1b3f573fSAndroid Build Coastguard Worker NSAssert(GPBExtensionIsRepeated(description_), 1071*1b3f573fSAndroid Build Coastguard Worker @"Only valid on repeated extensions"); 1072*1b3f573fSAndroid Build Coastguard Worker return GPBWireFormatForType(description_->dataType, 1073*1b3f573fSAndroid Build Coastguard Worker !GPBExtensionIsPacked(description_)); 1074*1b3f573fSAndroid Build Coastguard Worker} 1075*1b3f573fSAndroid Build Coastguard Worker 1076*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isRepeated { 1077*1b3f573fSAndroid Build Coastguard Worker return GPBExtensionIsRepeated(description_); 1078*1b3f573fSAndroid Build Coastguard Worker} 1079*1b3f573fSAndroid Build Coastguard Worker 1080*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isPackable { 1081*1b3f573fSAndroid Build Coastguard Worker return GPBExtensionIsPacked(description_); 1082*1b3f573fSAndroid Build Coastguard Worker} 1083*1b3f573fSAndroid Build Coastguard Worker 1084*1b3f573fSAndroid Build Coastguard Worker- (Class)msgClass { 1085*1b3f573fSAndroid Build Coastguard Worker return description_->messageOrGroupClass.clazz; 1086*1b3f573fSAndroid Build Coastguard Worker} 1087*1b3f573fSAndroid Build Coastguard Worker 1088*1b3f573fSAndroid Build Coastguard Worker- (Class)containingMessageClass { 1089*1b3f573fSAndroid Build Coastguard Worker return description_->extendedClass.clazz; 1090*1b3f573fSAndroid Build Coastguard Worker} 1091*1b3f573fSAndroid Build Coastguard Worker 1092*1b3f573fSAndroid Build Coastguard Worker- (GPBEnumDescriptor *)enumDescriptor { 1093*1b3f573fSAndroid Build Coastguard Worker if (description_->dataType == GPBDataTypeEnum) { 1094*1b3f573fSAndroid Build Coastguard Worker GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); 1095*1b3f573fSAndroid Build Coastguard Worker return enumDescriptor; 1096*1b3f573fSAndroid Build Coastguard Worker } 1097*1b3f573fSAndroid Build Coastguard Worker return nil; 1098*1b3f573fSAndroid Build Coastguard Worker} 1099*1b3f573fSAndroid Build Coastguard Worker 1100*1b3f573fSAndroid Build Coastguard Worker- (id)defaultValue { 1101*1b3f573fSAndroid Build Coastguard Worker if (GPBExtensionIsRepeated(description_)) { 1102*1b3f573fSAndroid Build Coastguard Worker return nil; 1103*1b3f573fSAndroid Build Coastguard Worker } 1104*1b3f573fSAndroid Build Coastguard Worker 1105*1b3f573fSAndroid Build Coastguard Worker switch (description_->dataType) { 1106*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 1107*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueBool); 1108*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 1109*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueFloat); 1110*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 1111*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueDouble); 1112*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 1113*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 1114*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 1115*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 1116*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueInt32); 1117*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 1118*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 1119*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 1120*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueInt64); 1121*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 1122*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 1123*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueUInt32); 1124*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 1125*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 1126*1b3f573fSAndroid Build Coastguard Worker return @(defaultValue_.valueUInt64); 1127*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 1128*1b3f573fSAndroid Build Coastguard Worker // Like message fields, the default is zero length data. 1129*1b3f573fSAndroid Build Coastguard Worker return (defaultValue_.valueData ? defaultValue_.valueData 1130*1b3f573fSAndroid Build Coastguard Worker : GPBEmptyNSData()); 1131*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 1132*1b3f573fSAndroid Build Coastguard Worker // Like message fields, the default is zero length string. 1133*1b3f573fSAndroid Build Coastguard Worker return (defaultValue_.valueString ? defaultValue_.valueString : @""); 1134*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 1135*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 1136*1b3f573fSAndroid Build Coastguard Worker return nil; 1137*1b3f573fSAndroid Build Coastguard Worker } 1138*1b3f573fSAndroid Build Coastguard Worker} 1139*1b3f573fSAndroid Build Coastguard Worker 1140*1b3f573fSAndroid Build Coastguard Worker- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other { 1141*1b3f573fSAndroid Build Coastguard Worker int32_t selfNumber = description_->fieldNumber; 1142*1b3f573fSAndroid Build Coastguard Worker int32_t otherNumber = other->description_->fieldNumber; 1143*1b3f573fSAndroid Build Coastguard Worker if (selfNumber < otherNumber) { 1144*1b3f573fSAndroid Build Coastguard Worker return NSOrderedAscending; 1145*1b3f573fSAndroid Build Coastguard Worker } else if (selfNumber == otherNumber) { 1146*1b3f573fSAndroid Build Coastguard Worker return NSOrderedSame; 1147*1b3f573fSAndroid Build Coastguard Worker } else { 1148*1b3f573fSAndroid Build Coastguard Worker return NSOrderedDescending; 1149*1b3f573fSAndroid Build Coastguard Worker } 1150*1b3f573fSAndroid Build Coastguard Worker} 1151*1b3f573fSAndroid Build Coastguard Worker 1152*1b3f573fSAndroid Build Coastguard Worker@end 1153*1b3f573fSAndroid Build Coastguard Worker 1154*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic pop 1155