GPBDescriptor.m 46 KB

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