OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 18 matching lines...) Expand all Loading... |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 #import "GPBDescriptor_PackagePrivate.h" | 31 #import "GPBDescriptor_PackagePrivate.h" |
32 | 32 |
33 #import <objc/runtime.h> | 33 #import <objc/runtime.h> |
34 | 34 |
35 #import "GPBUtilities_PackagePrivate.h" | 35 #import "GPBUtilities_PackagePrivate.h" |
36 #import "GPBWireFormat.h" | 36 #import "GPBWireFormat.h" |
37 #import "GPBMessage_PackagePrivate.h" | 37 #import "GPBMessage_PackagePrivate.h" |
38 | 38 |
39 // The address of this variable is used as a key for obj_getAssociatedObject. | 39 // Direct access is use for speed, to avoid even internally declaring things |
| 40 // read/write, etc. The warning is enabled in the project to ensure code calling |
| 41 // protos can turn on -Wdirect-ivar-access without issues. |
| 42 #pragma clang diagnostic push |
| 43 #pragma clang diagnostic ignored "-Wdirect-ivar-access" |
| 44 |
| 45 // The addresses of these variables are used as keys for objc_getAssociatedObjec
t. |
40 static const char kTextFormatExtraValueKey = 0; | 46 static const char kTextFormatExtraValueKey = 0; |
| 47 static const char kParentClassNameValueKey = 0; |
| 48 static const char kClassNameSuffixKey = 0; |
41 | 49 |
42 // Utility function to generate selectors on the fly. | 50 // Utility function to generate selectors on the fly. |
43 static SEL SelFromStrings(const char *prefix, const char *middle, | 51 static SEL SelFromStrings(const char *prefix, const char *middle, |
44 const char *suffix, BOOL takesArg) { | 52 const char *suffix, BOOL takesArg) { |
45 if (prefix == NULL && suffix == NULL && !takesArg) { | 53 if (prefix == NULL && suffix == NULL && !takesArg) { |
46 return sel_getUid(middle); | 54 return sel_getUid(middle); |
47 } | 55 } |
48 const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; | 56 const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0; |
49 const size_t middleLen = strlen(middle); | 57 const size_t middleLen = strlen(middle); |
50 const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; | 58 const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 } | 210 } |
203 } | 211 } |
204 } | 212 } |
205 } | 213 } |
206 | 214 |
207 - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)co
unt { | 215 - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)co
unt { |
208 extensionRanges_ = ranges; | 216 extensionRanges_ = ranges; |
209 extensionRangesCount_ = count; | 217 extensionRangesCount_ = count; |
210 } | 218 } |
211 | 219 |
| 220 - (void)setupContainingMessageClassName:(const char *)msgClassName { |
| 221 // Note: Only fetch the class here, can't send messages to it because |
| 222 // that could cause cycles back to this class within +initialize if |
| 223 // two messages have each other in fields (i.e. - they build a graph). |
| 224 NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); |
| 225 NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; |
| 226 objc_setAssociatedObject(self, &kParentClassNameValueKey, |
| 227 parentNameValue, |
| 228 OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
| 229 } |
| 230 |
| 231 - (void)setupMessageClassNameSuffix:(NSString *)suffix { |
| 232 if (suffix.length) { |
| 233 objc_setAssociatedObject(self, &kClassNameSuffixKey, |
| 234 suffix, |
| 235 OBJC_ASSOCIATION_RETAIN_NONATOMIC); |
| 236 } |
| 237 } |
| 238 |
212 - (NSString *)name { | 239 - (NSString *)name { |
213 return NSStringFromClass(messageClass_); | 240 return NSStringFromClass(messageClass_); |
214 } | 241 } |
215 | 242 |
| 243 - (GPBDescriptor *)containingType { |
| 244 NSValue *parentNameValue = |
| 245 objc_getAssociatedObject(self, &kParentClassNameValueKey); |
| 246 if (!parentNameValue) { |
| 247 return nil; |
| 248 } |
| 249 const char *parentName = [parentNameValue pointerValue]; |
| 250 Class parentClass = objc_getClass(parentName); |
| 251 NSAssert(parentClass, @"Class %s not defined", parentName); |
| 252 return [parentClass descriptor]; |
| 253 } |
| 254 |
| 255 - (NSString *)fullName { |
| 256 NSString *className = NSStringFromClass(self.messageClass); |
| 257 GPBFileDescriptor *file = self.file; |
| 258 NSString *objcPrefix = file.objcPrefix; |
| 259 if (objcPrefix && ![className hasPrefix:objcPrefix]) { |
| 260 NSAssert(0, |
| 261 @"Class didn't have correct prefix? (%@ - %@)", |
| 262 className, objcPrefix); |
| 263 return nil; |
| 264 } |
| 265 GPBDescriptor *parent = self.containingType; |
| 266 |
| 267 NSString *name = nil; |
| 268 if (parent) { |
| 269 NSString *parentClassName = NSStringFromClass(parent.messageClass); |
| 270 // The generator will add _Class to avoid reserved words, drop it. |
| 271 NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); |
| 272 if (suffix) { |
| 273 if (![parentClassName hasSuffix:suffix]) { |
| 274 NSAssert(0, |
| 275 @"ParentMessage class didn't have correct suffix? (%@ - %@)", |
| 276 className, suffix); |
| 277 return nil; |
| 278 } |
| 279 parentClassName = |
| 280 [parentClassName substringToIndex:(parentClassName.length - suffix.len
gth)]; |
| 281 } |
| 282 NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; |
| 283 if (![className hasPrefix:parentPrefix]) { |
| 284 NSAssert(0, |
| 285 @"Class didn't have the correct parent name prefix? (%@ - %@)", |
| 286 parentPrefix, className); |
| 287 return nil; |
| 288 } |
| 289 name = [className substringFromIndex:parentPrefix.length]; |
| 290 } else { |
| 291 name = [className substringFromIndex:objcPrefix.length]; |
| 292 } |
| 293 |
| 294 // The generator will add _Class to avoid reserved words, drop it. |
| 295 NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); |
| 296 if (suffix) { |
| 297 if (![name hasSuffix:suffix]) { |
| 298 NSAssert(0, |
| 299 @"Message class didn't have correct suffix? (%@ - %@)", |
| 300 name, suffix); |
| 301 return nil; |
| 302 } |
| 303 name = [name substringToIndex:(name.length - suffix.length)]; |
| 304 } |
| 305 |
| 306 NSString *prefix = (parent != nil ? parent.fullName : file.package); |
| 307 NSString *result; |
| 308 if (prefix.length > 0) { |
| 309 result = [NSString stringWithFormat:@"%@.%@", prefix, name]; |
| 310 } else { |
| 311 result = name; |
| 312 } |
| 313 return result; |
| 314 } |
| 315 |
216 - (id)copyWithZone:(NSZone *)zone { | 316 - (id)copyWithZone:(NSZone *)zone { |
217 #pragma unused(zone) | 317 #pragma unused(zone) |
218 return [self retain]; | 318 return [self retain]; |
219 } | 319 } |
220 | 320 |
221 - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { | 321 - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { |
222 for (GPBFieldDescriptor *descriptor in fields_) { | 322 for (GPBFieldDescriptor *descriptor in fields_) { |
223 if (GPBFieldNumber(descriptor) == fieldNumber) { | 323 if (GPBFieldNumber(descriptor) == fieldNumber) { |
224 return descriptor; | 324 return descriptor; |
225 } | 325 } |
(...skipping 16 matching lines...) Expand all Loading... |
242 return descriptor; | 342 return descriptor; |
243 } | 343 } |
244 } | 344 } |
245 return nil; | 345 return nil; |
246 } | 346 } |
247 | 347 |
248 @end | 348 @end |
249 | 349 |
250 @implementation GPBFileDescriptor { | 350 @implementation GPBFileDescriptor { |
251 NSString *package_; | 351 NSString *package_; |
| 352 NSString *objcPrefix_; |
252 GPBFileSyntax syntax_; | 353 GPBFileSyntax syntax_; |
253 } | 354 } |
254 | 355 |
255 @synthesize package = package_; | 356 @synthesize package = package_; |
| 357 @synthesize objcPrefix = objcPrefix_; |
256 @synthesize syntax = syntax_; | 358 @synthesize syntax = syntax_; |
257 | 359 |
258 - (instancetype)initWithPackage:(NSString *)package | 360 - (instancetype)initWithPackage:(NSString *)package |
| 361 objcPrefix:(NSString *)objcPrefix |
| 362 syntax:(GPBFileSyntax)syntax { |
| 363 self = [super init]; |
| 364 if (self) { |
| 365 package_ = [package copy]; |
| 366 objcPrefix_ = [objcPrefix copy]; |
| 367 syntax_ = syntax; |
| 368 } |
| 369 return self; |
| 370 } |
| 371 |
| 372 - (instancetype)initWithPackage:(NSString *)package |
259 syntax:(GPBFileSyntax)syntax { | 373 syntax:(GPBFileSyntax)syntax { |
260 self = [super init]; | 374 self = [super init]; |
261 if (self) { | 375 if (self) { |
262 package_ = [package copy]; | 376 package_ = [package copy]; |
263 syntax_ = syntax; | 377 syntax_ = syntax; |
264 } | 378 } |
265 return self; | 379 return self; |
266 } | 380 } |
267 | 381 |
| 382 - (void)dealloc { |
| 383 [package_ release]; |
| 384 [objcPrefix_ release]; |
| 385 [super dealloc]; |
| 386 } |
| 387 |
268 @end | 388 @end |
269 | 389 |
270 @implementation GPBOneofDescriptor | 390 @implementation GPBOneofDescriptor |
271 | 391 |
272 @synthesize fields = fields_; | 392 @synthesize fields = fields_; |
273 | 393 |
274 - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { | 394 - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields { |
275 self = [super init]; | 395 self = [super init]; |
276 if (self) { | 396 if (self) { |
277 name_ = name; | 397 name_ = name; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 (coreDesc->hasIndex != GPBNoHasBit) && | 518 (coreDesc->hasIndex != GPBNoHasBit) && |
399 ((syntax != GPBFileSyntaxProto3) || isMessage)) { | 519 ((syntax != GPBFileSyntaxProto3) || isMessage)) { |
400 hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); | 520 hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO); |
401 setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); | 521 setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES); |
402 } | 522 } |
403 } | 523 } |
404 | 524 |
405 // Extra type specific data. | 525 // Extra type specific data. |
406 if (isMessage) { | 526 if (isMessage) { |
407 const char *className = coreDesc->dataTypeSpecific.className; | 527 const char *className = coreDesc->dataTypeSpecific.className; |
| 528 // Note: Only fetch the class here, can't send messages to it because |
| 529 // that could cause cycles back to this class within +initialize if |
| 530 // two messages have each other in fields (i.e. - they build a graph). |
408 msgClass_ = objc_getClass(className); | 531 msgClass_ = objc_getClass(className); |
409 NSAssert(msgClass_, @"Class %s not defined", className); | 532 NSAssert(msgClass_, @"Class %s not defined", className); |
410 } else if (dataType == GPBDataTypeEnum) { | 533 } else if (dataType == GPBDataTypeEnum) { |
411 if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { | 534 if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) { |
412 enumHandling_.enumDescriptor_ = | 535 enumHandling_.enumDescriptor_ = |
413 coreDesc->dataTypeSpecific.enumDescFunc(); | 536 coreDesc->dataTypeSpecific.enumDescFunc(); |
414 } else { | 537 } else { |
415 enumHandling_.enumVerifier_ = | 538 enumHandling_.enumVerifier_ = |
416 coreDesc->dataTypeSpecific.enumVerifier; | 539 coreDesc->dataTypeSpecific.enumVerifier; |
417 } | 540 } |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 if (strcmp(nameAsCStr, valueName) == 0) { | 861 if (strcmp(nameAsCStr, valueName) == 0) { |
739 if (outValue) { | 862 if (outValue) { |
740 *outValue = values_[i]; | 863 *outValue = values_[i]; |
741 } | 864 } |
742 return YES; | 865 return YES; |
743 } | 866 } |
744 } | 867 } |
745 return NO; | 868 return NO; |
746 } | 869 } |
747 | 870 |
| 871 - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textForma
tName { |
| 872 if (nameOffsets_ == NULL) [self calcValueNameOffsets]; |
| 873 |
| 874 for (uint32_t i = 0; i < valueCount_; ++i) { |
| 875 int32_t value = values_[i]; |
| 876 NSString *valueTextFormatName = [self textFormatNameForValue:value]; |
| 877 if ([valueTextFormatName isEqual:textFormatName]) { |
| 878 if (outValue) { |
| 879 *outValue = value; |
| 880 } |
| 881 return YES; |
| 882 } |
| 883 } |
| 884 return NO; |
| 885 } |
| 886 |
748 - (NSString *)textFormatNameForValue:(int32_t)number { | 887 - (NSString *)textFormatNameForValue:(int32_t)number { |
749 if (nameOffsets_ == NULL) [self calcValueNameOffsets]; | 888 if (nameOffsets_ == NULL) [self calcValueNameOffsets]; |
750 | 889 |
751 // Find the EnumValue descriptor and its index. | 890 // Find the EnumValue descriptor and its index. |
752 BOOL foundIt = NO; | 891 BOOL foundIt = NO; |
753 uint32_t valueDescriptorIndex; | 892 uint32_t valueDescriptorIndex; |
754 for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; | 893 for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; |
755 ++valueDescriptorIndex) { | 894 ++valueDescriptorIndex) { |
756 if (values_[valueDescriptorIndex] == number) { | 895 if (values_[valueDescriptorIndex] == number) { |
757 foundIt = YES; | 896 foundIt = YES; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 GPBGenericValue defaultValue_; | 935 GPBGenericValue defaultValue_; |
797 } | 936 } |
798 | 937 |
799 @synthesize containingMessageClass = containingMessageClass_; | 938 @synthesize containingMessageClass = containingMessageClass_; |
800 | 939 |
801 - (instancetype)initWithExtensionDescription: | 940 - (instancetype)initWithExtensionDescription: |
802 (GPBExtensionDescription *)description { | 941 (GPBExtensionDescription *)description { |
803 if ((self = [super init])) { | 942 if ((self = [super init])) { |
804 description_ = description; | 943 description_ = description; |
805 | 944 |
806 #if DEBUG | 945 #if defined(DEBUG) && DEBUG |
807 const char *className = description->messageOrGroupClassName; | 946 const char *className = description->messageOrGroupClassName; |
808 if (className) { | 947 if (className) { |
809 NSAssert(objc_lookUpClass(className) != Nil, | 948 NSAssert(objc_lookUpClass(className) != Nil, |
810 @"Class %s not defined", className); | 949 @"Class %s not defined", className); |
811 } | 950 } |
812 #endif | 951 #endif |
813 | 952 |
814 if (description->extendedClass) { | 953 if (description->extendedClass) { |
815 Class containingClass = objc_lookUpClass(description->extendedClass); | 954 Class containingClass = objc_lookUpClass(description->extendedClass); |
816 NSAssert(containingClass, @"Class %s not defined", | 955 NSAssert(containingClass, @"Class %s not defined", |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 if (selfNumber < otherNumber) { | 1093 if (selfNumber < otherNumber) { |
955 return NSOrderedAscending; | 1094 return NSOrderedAscending; |
956 } else if (selfNumber == otherNumber) { | 1095 } else if (selfNumber == otherNumber) { |
957 return NSOrderedSame; | 1096 return NSOrderedSame; |
958 } else { | 1097 } else { |
959 return NSOrderedDescending; | 1098 return NSOrderedDescending; |
960 } | 1099 } |
961 } | 1100 } |
962 | 1101 |
963 @end | 1102 @end |
| 1103 |
| 1104 #pragma clang diagnostic pop |
OLD | NEW |