You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1923 lines
72 KiB

6 years ago
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #import "GPBUtilities_PackagePrivate.h"
  31. #import <objc/runtime.h>
  32. #import "GPBArray_PackagePrivate.h"
  33. #import "GPBDescriptor_PackagePrivate.h"
  34. #import "GPBDictionary_PackagePrivate.h"
  35. #import "GPBMessage_PackagePrivate.h"
  36. #import "GPBUnknownField.h"
  37. #import "GPBUnknownFieldSet.h"
  38. // Direct access is use for speed, to avoid even internally declaring things
  39. // read/write, etc. The warning is enabled in the project to ensure code calling
  40. // protos can turn on -Wdirect-ivar-access without issues.
  41. #pragma clang diagnostic push
  42. #pragma clang diagnostic ignored "-Wdirect-ivar-access"
  43. static void AppendTextFormatForMessage(GPBMessage *message,
  44. NSMutableString *toStr,
  45. NSString *lineIndent);
  46. NSData *GPBEmptyNSData(void) {
  47. static dispatch_once_t onceToken;
  48. static NSData *defaultNSData = nil;
  49. dispatch_once(&onceToken, ^{
  50. defaultNSData = [[NSData alloc] init];
  51. });
  52. return defaultNSData;
  53. }
  54. void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) {
  55. if (!initialMessage) {
  56. return;
  57. }
  58. // Use an array as a list to process to avoid recursion.
  59. NSMutableArray *todo = [NSMutableArray arrayWithObject:initialMessage];
  60. while (todo.count) {
  61. GPBMessage *msg = todo.lastObject;
  62. [todo removeLastObject];
  63. // Clear unknowns.
  64. msg.unknownFields = nil;
  65. // Handle the message fields.
  66. GPBDescriptor *descriptor = [[msg class] descriptor];
  67. for (GPBFieldDescriptor *field in descriptor->fields_) {
  68. if (!GPBFieldDataTypeIsMessage(field)) {
  69. continue;
  70. }
  71. switch (field.fieldType) {
  72. case GPBFieldTypeSingle:
  73. if (GPBGetHasIvarField(msg, field)) {
  74. GPBMessage *fieldMessage = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
  75. [todo addObject:fieldMessage];
  76. }
  77. break;
  78. case GPBFieldTypeRepeated: {
  79. NSArray *fieldMessages = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
  80. if (fieldMessages.count) {
  81. [todo addObjectsFromArray:fieldMessages];
  82. }
  83. break;
  84. }
  85. case GPBFieldTypeMap: {
  86. id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
  87. switch (field.mapKeyDataType) {
  88. case GPBDataTypeBool:
  89. [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  90. BOOL key, id _Nonnull object, BOOL * _Nonnull stop) {
  91. #pragma unused(key, stop)
  92. [todo addObject:object];
  93. }];
  94. break;
  95. case GPBDataTypeFixed32:
  96. case GPBDataTypeUInt32:
  97. [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  98. uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
  99. #pragma unused(key, stop)
  100. [todo addObject:object];
  101. }];
  102. break;
  103. case GPBDataTypeInt32:
  104. case GPBDataTypeSFixed32:
  105. case GPBDataTypeSInt32:
  106. [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  107. int32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
  108. #pragma unused(key, stop)
  109. [todo addObject:object];
  110. }];
  111. break;
  112. case GPBDataTypeFixed64:
  113. case GPBDataTypeUInt64:
  114. [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  115. uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
  116. #pragma unused(key, stop)
  117. [todo addObject:object];
  118. }];
  119. break;
  120. case GPBDataTypeInt64:
  121. case GPBDataTypeSFixed64:
  122. case GPBDataTypeSInt64:
  123. [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  124. int64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
  125. #pragma unused(key, stop)
  126. [todo addObject:object];
  127. }];
  128. break;
  129. case GPBDataTypeString:
  130. [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
  131. NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) {
  132. #pragma unused(key, stop)
  133. [todo addObject:obj];
  134. }];
  135. break;
  136. case GPBDataTypeFloat:
  137. case GPBDataTypeDouble:
  138. case GPBDataTypeEnum:
  139. case GPBDataTypeBytes:
  140. case GPBDataTypeGroup:
  141. case GPBDataTypeMessage:
  142. NSCAssert(NO, @"Aren't valid key types.");
  143. }
  144. break;
  145. } // switch(field.mapKeyDataType)
  146. } // switch(field.fieldType)
  147. } // for(fields)
  148. // Handle any extensions holding messages.
  149. for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) {
  150. if (!GPBDataTypeIsMessage(extension.dataType)) {
  151. continue;
  152. }
  153. if (extension.isRepeated) {
  154. NSArray *extMessages = [msg getExtension:extension];
  155. [todo addObjectsFromArray:extMessages];
  156. } else {
  157. GPBMessage *extMessage = [msg getExtension:extension];
  158. [todo addObject:extMessage];
  159. }
  160. } // for(extensionsCurrentlySet)
  161. } // while(todo.count)
  162. }
  163. // -- About Version Checks --
  164. // There's actually 3 places these checks all come into play:
  165. // 1. When the generated source is compile into .o files, the header check
  166. // happens. This is checking the protoc used matches the library being used
  167. // when making the .o.
  168. // 2. Every place a generated proto header is included in a developer's code,
  169. // the header check comes into play again. But this time it is checking that
  170. // the current library headers being used still support/match the ones for
  171. // the generated code.
  172. // 3. At runtime the final check here (GPBCheckRuntimeVersionsInternal), is
  173. // called from the generated code passing in values captured when the
  174. // generated code's .o was made. This checks that at runtime the generated
  175. // code and runtime library match.
  176. void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) {
  177. // NOTE: This is passing the value captured in the compiled code to check
  178. // against the values captured when the runtime support was compiled. This
  179. // ensures the library code isn't in a different framework/library that
  180. // was generated with a non matching version.
  181. if (GOOGLE_PROTOBUF_OBJC_VERSION < objcRuntimeVersion) {
  182. // Library is too old for headers.
  183. [NSException raise:NSInternalInconsistencyException
  184. format:@"Linked to ProtocolBuffer runtime version %d,"
  185. @" but code compiled needing atleast %d!",
  186. GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion];
  187. }
  188. if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
  189. // Headers are too old for library.
  190. [NSException raise:NSInternalInconsistencyException
  191. format:@"Proto generation source compiled against runtime"
  192. @" version %d, but this version of the runtime only"
  193. @" supports back to %d!",
  194. objcRuntimeVersion,
  195. GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
  196. }
  197. }
  198. // This api is no longer used for version checks. 30001 is the last version
  199. // using this old versioning model. When that support is removed, this function
  200. // can be removed (along with the declaration in GPBUtilities_PackagePrivate.h).
  201. void GPBCheckRuntimeVersionInternal(int32_t version) {
  202. GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION == 30001,
  203. time_to_remove_this_old_version_shim);
  204. if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) {
  205. [NSException raise:NSInternalInconsistencyException
  206. format:@"Linked to ProtocolBuffer runtime version %d,"
  207. @" but code compiled with version %d!",
  208. GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version];
  209. }
  210. }
  211. BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
  212. GPBDescriptor *descriptor = [self descriptor];
  213. GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
  214. return GPBMessageHasFieldSet(self, field);
  215. }
  216. BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
  217. if (self == nil || field == nil) return NO;
  218. // Repeated/Map don't use the bit, they check the count.
  219. if (GPBFieldIsMapOrArray(field)) {
  220. // Array/map type doesn't matter, since GPB*Array/NSArray and
  221. // GPB*Dictionary/NSDictionary all support -count;
  222. NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
  223. return (arrayOrMap.count > 0);
  224. } else {
  225. return GPBGetHasIvarField(self, field);
  226. }
  227. }
  228. void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
  229. // If not set, nothing to do.
  230. if (!GPBGetHasIvarField(self, field)) {
  231. return;
  232. }
  233. if (GPBFieldStoresObject(field)) {
  234. // Object types are handled slightly differently, they need to be released.
  235. uint8_t *storage = (uint8_t *)self->messageStorage_;
  236. id *typePtr = (id *)&storage[field->description_->offset];
  237. [*typePtr release];
  238. *typePtr = nil;
  239. } else {
  240. // POD types just need to clear the has bit as the Get* method will
  241. // fetch the default when needed.
  242. }
  243. GPBSetHasIvarField(self, field, NO);
  244. }
  245. BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
  246. NSCAssert(self->messageStorage_ != NULL,
  247. @"%@: All messages should have storage (from init)",
  248. [self class]);
  249. if (idx < 0) {
  250. NSCAssert(fieldNumber != 0, @"Invalid field number.");
  251. BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
  252. return hasIvar;
  253. } else {
  254. NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
  255. uint32_t byteIndex = idx / 32;
  256. uint32_t bitMask = (1 << (idx % 32));
  257. BOOL hasIvar =
  258. (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
  259. return hasIvar;
  260. }
  261. }
  262. uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
  263. NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.",
  264. [self class], idx);
  265. uint32_t result = self->messageStorage_->_has_storage_[-idx];
  266. return result;
  267. }
  268. void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
  269. BOOL value) {
  270. if (idx < 0) {
  271. NSCAssert(fieldNumber != 0, @"Invalid field number.");
  272. uint32_t *has_storage = self->messageStorage_->_has_storage_;
  273. has_storage[-idx] = (value ? fieldNumber : 0);
  274. } else {
  275. NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
  276. uint32_t *has_storage = self->messageStorage_->_has_storage_;
  277. uint32_t byte = idx / 32;
  278. uint32_t bitMask = (1 << (idx % 32));
  279. if (value) {
  280. has_storage[byte] |= bitMask;
  281. } else {
  282. has_storage[byte] &= ~bitMask;
  283. }
  284. }
  285. }
  286. void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
  287. int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) {
  288. uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex);
  289. if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
  290. // Do nothing/nothing set in the oneof.
  291. return;
  292. }
  293. // Like GPBClearMessageField(), free the memory if an objecttype is set,
  294. // pod types don't need to do anything.
  295. GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
  296. NSCAssert(fieldSet,
  297. @"%@: oneof set to something (%u) not in the oneof?",
  298. [self class], fieldNumberSet);
  299. if (fieldSet && GPBFieldStoresObject(fieldSet)) {
  300. uint8_t *storage = (uint8_t *)self->messageStorage_;
  301. id *typePtr = (id *)&storage[fieldSet->description_->offset];
  302. [*typePtr release];
  303. *typePtr = nil;
  304. }
  305. // Set to nothing stored in the oneof.
  306. // (field number doesn't matter since setting to nothing).
  307. GPBSetHasIvar(self, oneofHasIndex, 1, NO);
  308. }
  309. #pragma mark - IVar accessors
  310. //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
  311. //%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
  312. //% TYPE$S NAME$S GPBFieldDescriptor *field) {
  313. //% if (GPBGetHasIvarField(self, field)) {
  314. //% uint8_t *storage = (uint8_t *)self->messageStorage_;
  315. //% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
  316. //% return *typePtr;
  317. //% } else {
  318. //% return field.defaultValue.value##NAME;
  319. //% }
  320. //%}
  321. //%
  322. //%// Only exists for public api, no core code should use this.
  323. //%void GPBSetMessage##NAME##Field(GPBMessage *self,
  324. //% NAME$S GPBFieldDescriptor *field,
  325. //% NAME$S TYPE value) {
  326. //% if (self == nil || field == nil) return;
  327. //% GPBFileSyntax syntax = [self descriptor].file.syntax;
  328. //% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
  329. //%}
  330. //%
  331. //%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
  332. //% NAME$S GPBFieldDescriptor *field,
  333. //% NAME$S TYPE value,
  334. //% NAME$S GPBFileSyntax syntax) {
  335. //% GPBOneofDescriptor *oneof = field->containingOneof_;
  336. //% if (oneof) {
  337. //% GPBMessageFieldDescription *fieldDesc = field->description_;
  338. //% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  339. //% }
  340. //% NSCAssert(self->messageStorage_ != NULL,
  341. //% @"%@: All messages should have storage (from init)",
  342. //% [self class]);
  343. //%#if defined(__clang_analyzer__)
  344. //% if (self->messageStorage_ == NULL) return;
  345. //%#endif
  346. //% uint8_t *storage = (uint8_t *)self->messageStorage_;
  347. //% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
  348. //% *typePtr = value;
  349. //% // proto2: any value counts as having been set; proto3, it
  350. //% // has to be a non zero value or be in a oneof.
  351. //% BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  352. //% || (value != (TYPE)0)
  353. //% || (field->containingOneof_ != NULL));
  354. //% GPBSetHasIvarField(self, field, hasValue);
  355. //% GPBBecomeVisibleToAutocreator(self);
  356. //%}
  357. //%
  358. //%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE)
  359. //%// Only exists for public api, no core code should use this.
  360. //%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self,
  361. //% TYPE$S NAME$S GPBFieldDescriptor *field) {
  362. //% return (TYPE *)GPBGetObjectIvarWithField(self, field);
  363. //%}
  364. //%
  365. //%// Only exists for public api, no core code should use this.
  366. //%void GPBSetMessage##NAME##Field(GPBMessage *self,
  367. //% NAME$S GPBFieldDescriptor *field,
  368. //% NAME$S TYPE *value) {
  369. //% GPBSetObjectIvarWithField(self, field, (id)value);
  370. //%}
  371. //%
  372. // Object types are handled slightly differently, they need to be released
  373. // and retained.
  374. void GPBSetAutocreatedRetainedObjectIvarWithField(
  375. GPBMessage *self, GPBFieldDescriptor *field,
  376. id __attribute__((ns_consumed)) value) {
  377. uint8_t *storage = (uint8_t *)self->messageStorage_;
  378. id *typePtr = (id *)&storage[field->description_->offset];
  379. NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
  380. *typePtr = value;
  381. }
  382. void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
  383. GPBFieldDescriptor *field) {
  384. if (GPBGetHasIvarField(self, field)) {
  385. return;
  386. }
  387. uint8_t *storage = (uint8_t *)self->messageStorage_;
  388. id *typePtr = (id *)&storage[field->description_->offset];
  389. GPBMessage *oldValue = *typePtr;
  390. *typePtr = NULL;
  391. GPBClearMessageAutocreator(oldValue);
  392. [oldValue release];
  393. }
  394. // This exists only for briging some aliased types, nothing else should use it.
  395. static void GPBSetObjectIvarWithField(GPBMessage *self,
  396. GPBFieldDescriptor *field, id value) {
  397. if (self == nil || field == nil) return;
  398. GPBFileSyntax syntax = [self descriptor].file.syntax;
  399. GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
  400. syntax);
  401. }
  402. void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
  403. GPBFieldDescriptor *field, id value,
  404. GPBFileSyntax syntax) {
  405. GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
  406. syntax);
  407. }
  408. void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
  409. GPBFieldDescriptor *field,
  410. id value, GPBFileSyntax syntax) {
  411. NSCAssert(self->messageStorage_ != NULL,
  412. @"%@: All messages should have storage (from init)",
  413. [self class]);
  414. #if defined(__clang_analyzer__)
  415. if (self->messageStorage_ == NULL) return;
  416. #endif
  417. GPBDataType fieldType = GPBGetFieldDataType(field);
  418. BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
  419. BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
  420. #ifdef DEBUG
  421. if (value == nil && !isMapOrArray && !fieldIsMessage &&
  422. field.hasDefaultValue) {
  423. // Setting a message to nil is an obvious way to "clear" the value
  424. // as there is no way to set a non-empty default value for messages.
  425. //
  426. // For Strings and Bytes that have default values set it is not clear what
  427. // should be done when their value is set to nil. Is the intention just to
  428. // clear the set value and reset to default, or is the intention to set the
  429. // value to the empty string/data? Arguments can be made for both cases.
  430. // 'nil' has been abused as a replacement for an empty string/data in ObjC.
  431. // We decided to be consistent with all "object" types and clear the has
  432. // field, and fall back on the default value. The warning below will only
  433. // appear in debug, but the could should be changed so the intention is
  434. // clear.
  435. NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_);
  436. NSString *propName = field.name;
  437. NSString *className = self.descriptor.name;
  438. NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
  439. @"default values. Please use '%@.%@ = %@' if you want to set it to "
  440. @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
  441. @"'%@'. Defaulting to resetting default value.",
  442. className, propName, className, propName,
  443. (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
  444. className, hasSel, field.defaultValue.valueString);
  445. // Note: valueString, depending on the type, it could easily be
  446. // valueData/valueMessage.
  447. }
  448. #endif // DEBUG
  449. if (!isMapOrArray) {
  450. // Non repeated/map can be in an oneof, clear any existing value from the
  451. // oneof.
  452. GPBOneofDescriptor *oneof = field->containingOneof_;
  453. if (oneof) {
  454. GPBMessageFieldDescription *fieldDesc = field->description_;
  455. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  456. }
  457. // Clear "has" if they are being set to nil.
  458. BOOL setHasValue = (value != nil);
  459. // Under proto3, Bytes & String fields get cleared by resetting them to
  460. // their default (empty) values, so if they are set to something of length
  461. // zero, they are being cleared.
  462. if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
  463. ([value length] == 0)) {
  464. // Except, if the field was in a oneof, then it still gets recorded as
  465. // having been set so the state of the oneof can be serialized back out.
  466. if (!oneof) {
  467. setHasValue = NO;
  468. }
  469. if (setHasValue) {
  470. NSCAssert(value != nil, @"Should never be setting has for nil");
  471. } else {
  472. // The value passed in was retained, it must be released since we
  473. // aren't saving anything in the field.
  474. [value release];
  475. value = nil;
  476. }
  477. }
  478. GPBSetHasIvarField(self, field, setHasValue);
  479. }
  480. uint8_t *storage = (uint8_t *)self->messageStorage_;
  481. id *typePtr = (id *)&storage[field->description_->offset];
  482. id oldValue = *typePtr;
  483. *typePtr = value;
  484. if (oldValue) {
  485. if (isMapOrArray) {
  486. if (field.fieldType == GPBFieldTypeRepeated) {
  487. // If the old array was autocreated by us, then clear it.
  488. if (GPBDataTypeIsObject(fieldType)) {
  489. if ([oldValue isKindOfClass:[GPBAutocreatedArray class]]) {
  490. GPBAutocreatedArray *autoArray = oldValue;
  491. if (autoArray->_autocreator == self) {
  492. autoArray->_autocreator = nil;
  493. }
  494. }
  495. } else {
  496. // Type doesn't matter, it is a GPB*Array.
  497. GPBInt32Array *gpbArray = oldValue;
  498. if (gpbArray->_autocreator == self) {
  499. gpbArray->_autocreator = nil;
  500. }
  501. }
  502. } else { // GPBFieldTypeMap
  503. // If the old map was autocreated by us, then clear it.
  504. if ((field.mapKeyDataType == GPBDataTypeString) &&
  505. GPBDataTypeIsObject(fieldType)) {
  506. if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
  507. GPBAutocreatedDictionary *autoDict = oldValue;
  508. if (autoDict->_autocreator == self) {
  509. autoDict->_autocreator = nil;
  510. }
  511. }
  512. } else {
  513. // Type doesn't matter, it is a GPB*Dictionary.
  514. GPBInt32Int32Dictionary *gpbDict = oldValue;
  515. if (gpbDict->_autocreator == self) {
  516. gpbDict->_autocreator = nil;
  517. }
  518. }
  519. }
  520. } else if (fieldIsMessage) {
  521. // If the old message value was autocreated by us, then clear it.
  522. GPBMessage *oldMessageValue = oldValue;
  523. if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
  524. GPBClearMessageAutocreator(oldMessageValue);
  525. }
  526. }
  527. [oldValue release];
  528. }
  529. GPBBecomeVisibleToAutocreator(self);
  530. }
  531. id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
  532. GPBFieldDescriptor *field) {
  533. if (self->messageStorage_ == nil) {
  534. return nil;
  535. }
  536. uint8_t *storage = (uint8_t *)self->messageStorage_;
  537. id *typePtr = (id *)&storage[field->description_->offset];
  538. return *typePtr;
  539. }
  540. id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
  541. NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
  542. if (GPBGetHasIvarField(self, field)) {
  543. uint8_t *storage = (uint8_t *)self->messageStorage_;
  544. id *typePtr = (id *)&storage[field->description_->offset];
  545. return *typePtr;
  546. }
  547. // Not set...
  548. // Non messages (string/data), get their default.
  549. if (!GPBFieldDataTypeIsMessage(field)) {
  550. return field.defaultValue.valueMessage;
  551. }
  552. GPBPrepareReadOnlySemaphore(self);
  553. dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER);
  554. GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
  555. if (!result) {
  556. // For non repeated messages, create the object, set it and return it.
  557. // This object will not initially be visible via GPBGetHasIvar, so
  558. // we save its creator so it can become visible if it's mutated later.
  559. result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
  560. GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
  561. }
  562. dispatch_semaphore_signal(self->readOnlySemaphore_);
  563. return result;
  564. }
  565. // Only exists for public api, no core code should use this.
  566. int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
  567. GPBFileSyntax syntax = [self descriptor].file.syntax;
  568. return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
  569. }
  570. int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
  571. GPBFieldDescriptor *field,
  572. GPBFileSyntax syntax) {
  573. int32_t result = GPBGetMessageInt32Field(self, field);
  574. // If this is presevering unknown enums, make sure the value is valid before
  575. // returning it.
  576. if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
  577. ![field isValidEnumValue:result]) {
  578. result = kGPBUnrecognizedEnumeratorValue;
  579. }
  580. return result;
  581. }
  582. // Only exists for public api, no core code should use this.
  583. void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
  584. int32_t value) {
  585. GPBFileSyntax syntax = [self descriptor].file.syntax;
  586. GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
  587. }
  588. void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
  589. GPBFieldDescriptor *field, int32_t value,
  590. GPBFileSyntax syntax) {
  591. // Don't allow in unknown values. Proto3 can use the Raw method.
  592. if (![field isValidEnumValue:value]) {
  593. [NSException raise:NSInvalidArgumentException
  594. format:@"%@.%@: Attempt to set an unknown enum value (%d)",
  595. [self class], field.name, value];
  596. }
  597. GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
  598. }
  599. // Only exists for public api, no core code should use this.
  600. int32_t GPBGetMessageRawEnumField(GPBMessage *self,
  601. GPBFieldDescriptor *field) {
  602. int32_t result = GPBGetMessageInt32Field(self, field);
  603. return result;
  604. }
  605. // Only exists for public api, no core code should use this.
  606. void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
  607. int32_t value) {
  608. GPBFileSyntax syntax = [self descriptor].file.syntax;
  609. GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
  610. }
  611. BOOL GPBGetMessageBoolField(GPBMessage *self,
  612. GPBFieldDescriptor *field) {
  613. if (GPBGetHasIvarField(self, field)) {
  614. // Bools are stored in the has bits to avoid needing explicit space in the
  615. // storage structure.
  616. // (the field number passed to the HasIvar helper doesn't really matter
  617. // since the offset is never negative)
  618. GPBMessageFieldDescription *fieldDesc = field->description_;
  619. return GPBGetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number);
  620. } else {
  621. return field.defaultValue.valueBool;
  622. }
  623. }
  624. // Only exists for public api, no core code should use this.
  625. void GPBSetMessageBoolField(GPBMessage *self,
  626. GPBFieldDescriptor *field,
  627. BOOL value) {
  628. if (self == nil || field == nil) return;
  629. GPBFileSyntax syntax = [self descriptor].file.syntax;
  630. GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
  631. }
  632. void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
  633. GPBFieldDescriptor *field,
  634. BOOL value,
  635. GPBFileSyntax syntax) {
  636. GPBMessageFieldDescription *fieldDesc = field->description_;
  637. GPBOneofDescriptor *oneof = field->containingOneof_;
  638. if (oneof) {
  639. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  640. }
  641. // Bools are stored in the has bits to avoid needing explicit space in the
  642. // storage structure.
  643. // (the field number passed to the HasIvar helper doesn't really matter since
  644. // the offset is never negative)
  645. GPBSetHasIvar(self, (int32_t)(fieldDesc->offset), fieldDesc->number, value);
  646. // proto2: any value counts as having been set; proto3, it
  647. // has to be a non zero value or be in a oneof.
  648. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  649. || (value != (BOOL)0)
  650. || (field->containingOneof_ != NULL));
  651. GPBSetHasIvarField(self, field, hasValue);
  652. GPBBecomeVisibleToAutocreator(self);
  653. }
  654. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
  655. // This block of code is generated, do not edit it directly.
  656. int32_t GPBGetMessageInt32Field(GPBMessage *self,
  657. GPBFieldDescriptor *field) {
  658. if (GPBGetHasIvarField(self, field)) {
  659. uint8_t *storage = (uint8_t *)self->messageStorage_;
  660. int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
  661. return *typePtr;
  662. } else {
  663. return field.defaultValue.valueInt32;
  664. }
  665. }
  666. // Only exists for public api, no core code should use this.
  667. void GPBSetMessageInt32Field(GPBMessage *self,
  668. GPBFieldDescriptor *field,
  669. int32_t value) {
  670. if (self == nil || field == nil) return;
  671. GPBFileSyntax syntax = [self descriptor].file.syntax;
  672. GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
  673. }
  674. void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
  675. GPBFieldDescriptor *field,
  676. int32_t value,
  677. GPBFileSyntax syntax) {
  678. GPBOneofDescriptor *oneof = field->containingOneof_;
  679. if (oneof) {
  680. GPBMessageFieldDescription *fieldDesc = field->description_;
  681. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  682. }
  683. NSCAssert(self->messageStorage_ != NULL,
  684. @"%@: All messages should have storage (from init)",
  685. [self class]);
  686. #if defined(__clang_analyzer__)
  687. if (self->messageStorage_ == NULL) return;
  688. #endif
  689. uint8_t *storage = (uint8_t *)self->messageStorage_;
  690. int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
  691. *typePtr = value;
  692. // proto2: any value counts as having been set; proto3, it
  693. // has to be a non zero value or be in a oneof.
  694. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  695. || (value != (int32_t)0)
  696. || (field->containingOneof_ != NULL));
  697. GPBSetHasIvarField(self, field, hasValue);
  698. GPBBecomeVisibleToAutocreator(self);
  699. }
  700. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
  701. // This block of code is generated, do not edit it directly.
  702. uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
  703. GPBFieldDescriptor *field) {
  704. if (GPBGetHasIvarField(self, field)) {
  705. uint8_t *storage = (uint8_t *)self->messageStorage_;
  706. uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
  707. return *typePtr;
  708. } else {
  709. return field.defaultValue.valueUInt32;
  710. }
  711. }
  712. // Only exists for public api, no core code should use this.
  713. void GPBSetMessageUInt32Field(GPBMessage *self,
  714. GPBFieldDescriptor *field,
  715. uint32_t value) {
  716. if (self == nil || field == nil) return;
  717. GPBFileSyntax syntax = [self descriptor].file.syntax;
  718. GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
  719. }
  720. void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
  721. GPBFieldDescriptor *field,
  722. uint32_t value,
  723. GPBFileSyntax syntax) {
  724. GPBOneofDescriptor *oneof = field->containingOneof_;
  725. if (oneof) {
  726. GPBMessageFieldDescription *fieldDesc = field->description_;
  727. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  728. }
  729. NSCAssert(self->messageStorage_ != NULL,
  730. @"%@: All messages should have storage (from init)",
  731. [self class]);
  732. #if defined(__clang_analyzer__)
  733. if (self->messageStorage_ == NULL) return;
  734. #endif
  735. uint8_t *storage = (uint8_t *)self->messageStorage_;
  736. uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
  737. *typePtr = value;
  738. // proto2: any value counts as having been set; proto3, it
  739. // has to be a non zero value or be in a oneof.
  740. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  741. || (value != (uint32_t)0)
  742. || (field->containingOneof_ != NULL));
  743. GPBSetHasIvarField(self, field, hasValue);
  744. GPBBecomeVisibleToAutocreator(self);
  745. }
  746. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
  747. // This block of code is generated, do not edit it directly.
  748. int64_t GPBGetMessageInt64Field(GPBMessage *self,
  749. GPBFieldDescriptor *field) {
  750. if (GPBGetHasIvarField(self, field)) {
  751. uint8_t *storage = (uint8_t *)self->messageStorage_;
  752. int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
  753. return *typePtr;
  754. } else {
  755. return field.defaultValue.valueInt64;
  756. }
  757. }
  758. // Only exists for public api, no core code should use this.
  759. void GPBSetMessageInt64Field(GPBMessage *self,
  760. GPBFieldDescriptor *field,
  761. int64_t value) {
  762. if (self == nil || field == nil) return;
  763. GPBFileSyntax syntax = [self descriptor].file.syntax;
  764. GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
  765. }
  766. void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
  767. GPBFieldDescriptor *field,
  768. int64_t value,
  769. GPBFileSyntax syntax) {
  770. GPBOneofDescriptor *oneof = field->containingOneof_;
  771. if (oneof) {
  772. GPBMessageFieldDescription *fieldDesc = field->description_;
  773. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  774. }
  775. NSCAssert(self->messageStorage_ != NULL,
  776. @"%@: All messages should have storage (from init)",
  777. [self class]);
  778. #if defined(__clang_analyzer__)
  779. if (self->messageStorage_ == NULL) return;
  780. #endif
  781. uint8_t *storage = (uint8_t *)self->messageStorage_;
  782. int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
  783. *typePtr = value;
  784. // proto2: any value counts as having been set; proto3, it
  785. // has to be a non zero value or be in a oneof.
  786. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  787. || (value != (int64_t)0)
  788. || (field->containingOneof_ != NULL));
  789. GPBSetHasIvarField(self, field, hasValue);
  790. GPBBecomeVisibleToAutocreator(self);
  791. }
  792. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
  793. // This block of code is generated, do not edit it directly.
  794. uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
  795. GPBFieldDescriptor *field) {
  796. if (GPBGetHasIvarField(self, field)) {
  797. uint8_t *storage = (uint8_t *)self->messageStorage_;
  798. uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
  799. return *typePtr;
  800. } else {
  801. return field.defaultValue.valueUInt64;
  802. }
  803. }
  804. // Only exists for public api, no core code should use this.
  805. void GPBSetMessageUInt64Field(GPBMessage *self,
  806. GPBFieldDescriptor *field,
  807. uint64_t value) {
  808. if (self == nil || field == nil) return;
  809. GPBFileSyntax syntax = [self descriptor].file.syntax;
  810. GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
  811. }
  812. void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
  813. GPBFieldDescriptor *field,
  814. uint64_t value,
  815. GPBFileSyntax syntax) {
  816. GPBOneofDescriptor *oneof = field->containingOneof_;
  817. if (oneof) {
  818. GPBMessageFieldDescription *fieldDesc = field->description_;
  819. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  820. }
  821. NSCAssert(self->messageStorage_ != NULL,
  822. @"%@: All messages should have storage (from init)",
  823. [self class]);
  824. #if defined(__clang_analyzer__)
  825. if (self->messageStorage_ == NULL) return;
  826. #endif
  827. uint8_t *storage = (uint8_t *)self->messageStorage_;
  828. uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
  829. *typePtr = value;
  830. // proto2: any value counts as having been set; proto3, it
  831. // has to be a non zero value or be in a oneof.
  832. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  833. || (value != (uint64_t)0)
  834. || (field->containingOneof_ != NULL));
  835. GPBSetHasIvarField(self, field, hasValue);
  836. GPBBecomeVisibleToAutocreator(self);
  837. }
  838. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
  839. // This block of code is generated, do not edit it directly.
  840. float GPBGetMessageFloatField(GPBMessage *self,
  841. GPBFieldDescriptor *field) {
  842. if (GPBGetHasIvarField(self, field)) {
  843. uint8_t *storage = (uint8_t *)self->messageStorage_;
  844. float *typePtr = (float *)&storage[field->description_->offset];
  845. return *typePtr;
  846. } else {
  847. return field.defaultValue.valueFloat;
  848. }
  849. }
  850. // Only exists for public api, no core code should use this.
  851. void GPBSetMessageFloatField(GPBMessage *self,
  852. GPBFieldDescriptor *field,
  853. float value) {
  854. if (self == nil || field == nil) return;
  855. GPBFileSyntax syntax = [self descriptor].file.syntax;
  856. GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
  857. }
  858. void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
  859. GPBFieldDescriptor *field,
  860. float value,
  861. GPBFileSyntax syntax) {
  862. GPBOneofDescriptor *oneof = field->containingOneof_;
  863. if (oneof) {
  864. GPBMessageFieldDescription *fieldDesc = field->description_;
  865. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  866. }
  867. NSCAssert(self->messageStorage_ != NULL,
  868. @"%@: All messages should have storage (from init)",
  869. [self class]);
  870. #if defined(__clang_analyzer__)
  871. if (self->messageStorage_ == NULL) return;
  872. #endif
  873. uint8_t *storage = (uint8_t *)self->messageStorage_;
  874. float *typePtr = (float *)&storage[field->description_->offset];
  875. *typePtr = value;
  876. // proto2: any value counts as having been set; proto3, it
  877. // has to be a non zero value or be in a oneof.
  878. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  879. || (value != (float)0)
  880. || (field->containingOneof_ != NULL));
  881. GPBSetHasIvarField(self, field, hasValue);
  882. GPBBecomeVisibleToAutocreator(self);
  883. }
  884. //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
  885. // This block of code is generated, do not edit it directly.
  886. double GPBGetMessageDoubleField(GPBMessage *self,
  887. GPBFieldDescriptor *field) {
  888. if (GPBGetHasIvarField(self, field)) {
  889. uint8_t *storage = (uint8_t *)self->messageStorage_;
  890. double *typePtr = (double *)&storage[field->description_->offset];
  891. return *typePtr;
  892. } else {
  893. return field.defaultValue.valueDouble;
  894. }
  895. }
  896. // Only exists for public api, no core code should use this.
  897. void GPBSetMessageDoubleField(GPBMessage *self,
  898. GPBFieldDescriptor *field,
  899. double value) {
  900. if (self == nil || field == nil) return;
  901. GPBFileSyntax syntax = [self descriptor].file.syntax;
  902. GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
  903. }
  904. void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
  905. GPBFieldDescriptor *field,
  906. double value,
  907. GPBFileSyntax syntax) {
  908. GPBOneofDescriptor *oneof = field->containingOneof_;
  909. if (oneof) {
  910. GPBMessageFieldDescription *fieldDesc = field->description_;
  911. GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number);
  912. }
  913. NSCAssert(self->messageStorage_ != NULL,
  914. @"%@: All messages should have storage (from init)",
  915. [self class]);
  916. #if defined(__clang_analyzer__)
  917. if (self->messageStorage_ == NULL) return;
  918. #endif
  919. uint8_t *storage = (uint8_t *)self->messageStorage_;
  920. double *typePtr = (double *)&storage[field->description_->offset];
  921. *typePtr = value;
  922. // proto2: any value counts as having been set; proto3, it
  923. // has to be a non zero value or be in a oneof.
  924. BOOL hasValue = ((syntax == GPBFileSyntaxProto2)
  925. || (value != (double)0)
  926. || (field->containingOneof_ != NULL));
  927. GPBSetHasIvarField(self, field, hasValue);
  928. GPBBecomeVisibleToAutocreator(self);
  929. }
  930. //%PDDM-EXPAND-END (6 expansions)
  931. // Aliases are function calls that are virtually the same.
  932. //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString)
  933. // This block of code is generated, do not edit it directly.
  934. // Only exists for public api, no core code should use this.
  935. NSString *GPBGetMessageStringField(GPBMessage *self,
  936. GPBFieldDescriptor *field) {
  937. return (NSString *)GPBGetObjectIvarWithField(self, field);
  938. }
  939. // Only exists for public api, no core code should use this.
  940. void GPBSetMessageStringField(GPBMessage *self,
  941. GPBFieldDescriptor *field,
  942. NSString *value) {
  943. GPBSetObjectIvarWithField(self, field, (id)value);
  944. }
  945. //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData)
  946. // This block of code is generated, do not edit it directly.
  947. // Only exists for public api, no core code should use this.
  948. NSData *GPBGetMessageBytesField(GPBMessage *self,
  949. GPBFieldDescriptor *field) {
  950. return (NSData *)GPBGetObjectIvarWithField(self, field);
  951. }
  952. // Only exists for public api, no core code should use this.
  953. void GPBSetMessageBytesField(GPBMessage *self,
  954. GPBFieldDescriptor *field,
  955. NSData *value) {
  956. GPBSetObjectIvarWithField(self, field, (id)value);
  957. }
  958. //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
  959. // This block of code is generated, do not edit it directly.
  960. // Only exists for public api, no core code should use this.
  961. GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
  962. GPBFieldDescriptor *field) {
  963. return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
  964. }
  965. // Only exists for public api, no core code should use this.
  966. void GPBSetMessageMessageField(GPBMessage *self,
  967. GPBFieldDescriptor *field,
  968. GPBMessage *value) {
  969. GPBSetObjectIvarWithField(self, field, (id)value);
  970. }
  971. //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
  972. // This block of code is generated, do not edit it directly.
  973. // Only exists for public api, no core code should use this.
  974. GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
  975. GPBFieldDescriptor *field) {
  976. return (GPBMessage *)GPBGetObjectIvarWithField(self, field);
  977. }
  978. // Only exists for public api, no core code should use this.
  979. void GPBSetMessageGroupField(GPBMessage *self,
  980. GPBFieldDescriptor *field,
  981. GPBMessage *value) {
  982. GPBSetObjectIvarWithField(self, field, (id)value);
  983. }
  984. //%PDDM-EXPAND-END (4 expansions)
  985. // GPBGetMessageRepeatedField is defined in GPBMessage.m
  986. // Only exists for public api, no core code should use this.
  987. void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) {
  988. #if defined(DEBUG) && DEBUG
  989. if (field.fieldType != GPBFieldTypeRepeated) {
  990. [NSException raise:NSInvalidArgumentException
  991. format:@"%@.%@ is not a repeated field.",
  992. [self class], field.name];
  993. }
  994. Class expectedClass = Nil;
  995. switch (GPBGetFieldDataType(field)) {
  996. case GPBDataTypeBool:
  997. expectedClass = [GPBBoolArray class];
  998. break;
  999. case GPBDataTypeSFixed32:
  1000. case GPBDataTypeInt32:
  1001. case GPBDataTypeSInt32:
  1002. expectedClass = [GPBInt32Array class];
  1003. break;
  1004. case GPBDataTypeFixed32:
  1005. case GPBDataTypeUInt32:
  1006. expectedClass = [GPBUInt32Array class];
  1007. break;
  1008. case GPBDataTypeSFixed64:
  1009. case GPBDataTypeInt64:
  1010. case GPBDataTypeSInt64:
  1011. expectedClass = [GPBInt64Array class];
  1012. break;
  1013. case GPBDataTypeFixed64:
  1014. case GPBDataTypeUInt64:
  1015. expectedClass = [GPBUInt64Array class];
  1016. break;
  1017. case GPBDataTypeFloat:
  1018. expectedClass = [GPBFloatArray class];
  1019. break;
  1020. case GPBDataTypeDouble:
  1021. expectedClass = [GPBDoubleArray class];
  1022. break;
  1023. case GPBDataTypeBytes:
  1024. case GPBDataTypeString:
  1025. case GPBDataTypeMessage:
  1026. case GPBDataTypeGroup:
  1027. expectedClass = [NSMutableArray class];
  1028. break;
  1029. case GPBDataTypeEnum:
  1030. expectedClass = [GPBEnumArray class];
  1031. break;
  1032. }
  1033. if (array && ![array isKindOfClass:expectedClass]) {
  1034. [NSException raise:NSInvalidArgumentException
  1035. format:@"%@.%@: Expected %@ object, got %@.",
  1036. [self class], field.name, expectedClass, [array class]];
  1037. }
  1038. #endif
  1039. GPBSetObjectIvarWithField(self, field, array);
  1040. }
  1041. #if defined(DEBUG) && DEBUG
  1042. static NSString *TypeToStr(GPBDataType dataType) {
  1043. switch (dataType) {
  1044. case GPBDataTypeBool:
  1045. return @"Bool";
  1046. case GPBDataTypeSFixed32:
  1047. case GPBDataTypeInt32:
  1048. case GPBDataTypeSInt32:
  1049. return @"Int32";
  1050. case GPBDataTypeFixed32:
  1051. case GPBDataTypeUInt32:
  1052. return @"UInt32";
  1053. case GPBDataTypeSFixed64:
  1054. case GPBDataTypeInt64:
  1055. case GPBDataTypeSInt64:
  1056. return @"Int64";
  1057. case GPBDataTypeFixed64:
  1058. case GPBDataTypeUInt64:
  1059. return @"UInt64";
  1060. case GPBDataTypeFloat:
  1061. return @"Float";
  1062. case GPBDataTypeDouble:
  1063. return @"Double";
  1064. case GPBDataTypeBytes:
  1065. case GPBDataTypeString:
  1066. case GPBDataTypeMessage:
  1067. case GPBDataTypeGroup:
  1068. return @"Object";
  1069. case GPBDataTypeEnum:
  1070. return @"Bool";
  1071. }
  1072. }
  1073. #endif
  1074. // GPBGetMessageMapField is defined in GPBMessage.m
  1075. // Only exists for public api, no core code should use this.
  1076. void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
  1077. id dictionary) {
  1078. #if defined(DEBUG) && DEBUG
  1079. if (field.fieldType != GPBFieldTypeMap) {
  1080. [NSException raise:NSInvalidArgumentException
  1081. format:@"%@.%@ is not a map<> field.",
  1082. [self class], field.name];
  1083. }
  1084. if (dictionary) {
  1085. GPBDataType keyDataType = field.mapKeyDataType;
  1086. GPBDataType valueDataType = GPBGetFieldDataType(field);
  1087. NSString *keyStr = TypeToStr(keyDataType);
  1088. NSString *valueStr = TypeToStr(valueDataType);
  1089. if (keyDataType == GPBDataTypeString) {
  1090. keyStr = @"String";
  1091. }
  1092. Class expectedClass = Nil;
  1093. if ((keyDataType == GPBDataTypeString) &&
  1094. GPBDataTypeIsObject(valueDataType)) {
  1095. expectedClass = [NSMutableDictionary class];
  1096. } else {
  1097. NSString *className =
  1098. [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
  1099. expectedClass = NSClassFromString(className);
  1100. NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
  1101. }
  1102. if (![dictionary isKindOfClass:expectedClass]) {
  1103. [NSException raise:NSInvalidArgumentException
  1104. format:@"%@.%@: Expected %@ object, got %@.",
  1105. [self class], field.name, expectedClass,
  1106. [dictionary class]];
  1107. }
  1108. }
  1109. #endif
  1110. GPBSetObjectIvarWithField(self, field, dictionary);
  1111. }
  1112. #pragma mark - Misc Dynamic Runtime Utils
  1113. const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
  1114. Protocol *protocol =
  1115. objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
  1116. struct objc_method_description description =
  1117. protocol_getMethodDescription(protocol, selector, NO, instanceSel);
  1118. return description.types;
  1119. }
  1120. #pragma mark - Text Format Support
  1121. static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
  1122. [destStr appendString:@"\""];
  1123. NSUInteger len = [toPrint length];
  1124. for (NSUInteger i = 0; i < len; ++i) {
  1125. unichar aChar = [toPrint characterAtIndex:i];
  1126. switch (aChar) {
  1127. case '\n': [destStr appendString:@"\\n"]; break;
  1128. case '\r': [destStr appendString:@"\\r"]; break;
  1129. case '\t': [destStr appendString:@"\\t"]; break;
  1130. case '\"': [destStr appendString:@"\\\""]; break;
  1131. case '\'': [destStr appendString:@"\\\'"]; break;
  1132. case '\\': [destStr appendString:@"\\\\"]; break;
  1133. default:
  1134. // This differs slightly from the C++ code in that the C++ doesn't
  1135. // generate UTF8; it looks at the string in UTF8, but escapes every
  1136. // byte > 0x7E.
  1137. if (aChar < 0x20) {
  1138. [destStr appendFormat:@"\\%d%d%d",
  1139. (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
  1140. } else {
  1141. [destStr appendFormat:@"%C", aChar];
  1142. }
  1143. break;
  1144. }
  1145. }
  1146. [destStr appendString:@"\""];
  1147. }
  1148. static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
  1149. const char *src = (const char *)[buffer bytes];
  1150. size_t srcLen = [buffer length];
  1151. [destStr appendString:@"\""];
  1152. for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
  1153. switch (*src) {
  1154. case '\n': [destStr appendString:@"\\n"]; break;
  1155. case '\r': [destStr appendString:@"\\r"]; break;
  1156. case '\t': [destStr appendString:@"\\t"]; break;
  1157. case '\"': [destStr appendString:@"\\\""]; break;
  1158. case '\'': [destStr appendString:@"\\\'"]; break;
  1159. case '\\': [destStr appendString:@"\\\\"]; break;
  1160. default:
  1161. if (isprint(*src)) {
  1162. [destStr appendFormat:@"%c", *src];
  1163. } else {
  1164. // NOTE: doing hex means you have to worry about the letter after
  1165. // the hex being another hex char and forcing that to be escaped, so
  1166. // use octal to keep it simple.
  1167. [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
  1168. }
  1169. break;
  1170. }
  1171. }
  1172. [destStr appendString:@"\""];
  1173. }
  1174. static void AppendTextFormatForMapMessageField(
  1175. id map, GPBFieldDescriptor *field, NSMutableString *toStr,
  1176. NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
  1177. GPBDataType keyDataType = field.mapKeyDataType;
  1178. GPBDataType valueDataType = GPBGetFieldDataType(field);
  1179. BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
  1180. NSString *msgStartFirst =
  1181. [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
  1182. NSString *msgStart =
  1183. [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
  1184. NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
  1185. NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent];
  1186. NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent,
  1187. (isMessageValue ? "" : ":")];
  1188. __block BOOL isFirst = YES;
  1189. if ((keyDataType == GPBDataTypeString) &&
  1190. GPBDataTypeIsObject(valueDataType)) {
  1191. // map is an NSDictionary.
  1192. NSDictionary *dict = map;
  1193. [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
  1194. #pragma unused(stop)
  1195. [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
  1196. isFirst = NO;
  1197. [toStr appendString:keyLine];
  1198. AppendStringEscaped(key, toStr);
  1199. [toStr appendString:@"\n"];
  1200. [toStr appendString:valueLine];
  1201. #pragma clang diagnostic push
  1202. #pragma clang diagnostic ignored "-Wswitch-enum"
  1203. switch (valueDataType) {
  1204. case GPBDataTypeString:
  1205. AppendStringEscaped(value, toStr);
  1206. break;
  1207. case GPBDataTypeBytes:
  1208. AppendBufferAsString(value, toStr);
  1209. break;
  1210. case GPBDataTypeMessage:
  1211. [toStr appendString:@"{\n"];
  1212. NSString *subIndent = [lineIndent stringByAppendingString:@" "];
  1213. AppendTextFormatForMessage(value, toStr, subIndent);
  1214. [toStr appendFormat:@"%@ }", lineIndent];
  1215. break;
  1216. default:
  1217. NSCAssert(NO, @"Can't happen");
  1218. break;
  1219. }
  1220. #pragma clang diagnostic pop
  1221. [toStr appendString:@"\n"];
  1222. [toStr appendString:msgEnd];
  1223. }];
  1224. } else {
  1225. // map is one of the GPB*Dictionary classes, type doesn't matter.
  1226. GPBInt32Int32Dictionary *dict = map;
  1227. [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
  1228. [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
  1229. isFirst = NO;
  1230. // Key always is a NSString.
  1231. if (keyDataType == GPBDataTypeString) {
  1232. [toStr appendString:keyLine];
  1233. AppendStringEscaped(keyObj, toStr);
  1234. [toStr appendString:@"\n"];
  1235. } else {
  1236. [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
  1237. }
  1238. [toStr appendString:valueLine];
  1239. #pragma clang diagnostic push
  1240. #pragma clang diagnostic ignored "-Wswitch-enum"
  1241. switch (valueDataType) {
  1242. case GPBDataTypeString:
  1243. AppendStringEscaped(valueObj, toStr);
  1244. break;
  1245. case GPBDataTypeBytes:
  1246. AppendBufferAsString(valueObj, toStr);
  1247. break;
  1248. case GPBDataTypeMessage:
  1249. [toStr appendString:@"{\n"];
  1250. NSString *subIndent = [lineIndent stringByAppendingString:@" "];
  1251. AppendTextFormatForMessage(valueObj, toStr, subIndent);
  1252. [toStr appendFormat:@"%@ }", lineIndent];
  1253. break;
  1254. case GPBDataTypeEnum: {
  1255. int32_t enumValue = [valueObj intValue];
  1256. NSString *valueStr = nil;
  1257. GPBEnumDescriptor *descriptor = field.enumDescriptor;
  1258. if (descriptor) {
  1259. valueStr = [descriptor textFormatNameForValue:enumValue];
  1260. }
  1261. if (valueStr) {
  1262. [toStr appendString:valueStr];
  1263. } else {
  1264. [toStr appendFormat:@"%d", enumValue];
  1265. }
  1266. break;
  1267. }
  1268. default:
  1269. NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen");
  1270. // Everything else is a NSString.
  1271. [toStr appendString:valueObj];
  1272. break;
  1273. }
  1274. #pragma clang diagnostic pop
  1275. [toStr appendString:@"\n"];
  1276. [toStr appendString:msgEnd];
  1277. }];
  1278. }
  1279. }
  1280. static void AppendTextFormatForMessageField(GPBMessage *message,
  1281. GPBFieldDescriptor *field,
  1282. NSMutableString *toStr,
  1283. NSString *lineIndent) {
  1284. id arrayOrMap;
  1285. NSUInteger count;
  1286. GPBFieldType fieldType = field.fieldType;
  1287. switch (fieldType) {
  1288. case GPBFieldTypeSingle:
  1289. arrayOrMap = nil;
  1290. count = (GPBGetHasIvarField(message, field) ? 1 : 0);
  1291. break;
  1292. case GPBFieldTypeRepeated:
  1293. // Will be NSArray or GPB*Array, type doesn't matter, they both
  1294. // implement count.
  1295. arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
  1296. count = [(NSArray *)arrayOrMap count];
  1297. break;
  1298. case GPBFieldTypeMap: {
  1299. // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter,
  1300. // they both implement count.
  1301. arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
  1302. count = [(NSDictionary *)arrayOrMap count];
  1303. break;
  1304. }
  1305. }
  1306. if (count == 0) {
  1307. // Nothing to print, out of here.
  1308. return;
  1309. }
  1310. NSString *lineEnding = @"";
  1311. // If the name can't be reversed or support for extra info was turned off,
  1312. // this can return nil.
  1313. NSString *fieldName = [field textFormatName];
  1314. if ([fieldName length] == 0) {
  1315. fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
  1316. // If there is only one entry, put the objc name as a comment, other wise
  1317. // add it before the repeated values.
  1318. if (count > 1) {
  1319. [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
  1320. } else {
  1321. lineEnding = [NSString stringWithFormat:@" # %@", field.name];
  1322. }
  1323. }
  1324. if (fieldType == GPBFieldTypeMap) {
  1325. AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent,
  1326. fieldName, lineEnding);
  1327. return;
  1328. }
  1329. id array = arrayOrMap;
  1330. const BOOL isRepeated = (array != nil);
  1331. GPBDataType fieldDataType = GPBGetFieldDataType(field);
  1332. BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
  1333. for (NSUInteger j = 0; j < count; ++j) {
  1334. // Start the line.
  1335. [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
  1336. (isMessageField ? "" : ":")];
  1337. // The value.
  1338. switch (fieldDataType) {
  1339. #define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \
  1340. case GPBDataType##GPBDATATYPE: { \
  1341. CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \
  1342. : GPBGetMessage##REAL_TYPE##Field(message, field)); \
  1343. [toStr appendFormat:__VA_ARGS__, v]; \
  1344. break; \
  1345. }
  1346. FIELD_CASE(Int32, int32_t, Int32, @"%d")
  1347. FIELD_CASE(SInt32, int32_t, Int32, @"%d")
  1348. FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
  1349. FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
  1350. FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
  1351. FIELD_CASE(Int64, int64_t, Int64, @"%lld")
  1352. FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
  1353. FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
  1354. FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
  1355. FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
  1356. FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
  1357. FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
  1358. #undef FIELD_CASE
  1359. case GPBDataTypeEnum: {
  1360. int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
  1361. : GPBGetMessageInt32Field(message, field));
  1362. NSString *valueStr = nil;
  1363. GPBEnumDescriptor *descriptor = field.enumDescriptor;
  1364. if (descriptor) {
  1365. valueStr = [descriptor textFormatNameForValue:v];
  1366. }
  1367. if (valueStr) {
  1368. [toStr appendString:valueStr];
  1369. } else {
  1370. [toStr appendFormat:@"%d", v];
  1371. }
  1372. break;
  1373. }
  1374. case GPBDataTypeBool: {
  1375. BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
  1376. : GPBGetMessageBoolField(message, field));
  1377. [toStr appendString:(v ? @"true" : @"false")];
  1378. break;
  1379. }
  1380. case GPBDataTypeString: {
  1381. NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
  1382. : GPBGetMessageStringField(message, field));
  1383. AppendStringEscaped(v, toStr);
  1384. break;
  1385. }
  1386. case GPBDataTypeBytes: {
  1387. NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
  1388. : GPBGetMessageBytesField(message, field));
  1389. AppendBufferAsString(v, toStr);
  1390. break;
  1391. }
  1392. case GPBDataTypeGroup:
  1393. case GPBDataTypeMessage: {
  1394. GPBMessage *v =
  1395. (isRepeated ? [(NSArray *)array objectAtIndex:j]
  1396. : GPBGetObjectIvarWithField(message, field));
  1397. [toStr appendFormat:@"{%@\n", lineEnding];
  1398. NSString *subIndent = [lineIndent stringByAppendingString:@" "];
  1399. AppendTextFormatForMessage(v, toStr, subIndent);
  1400. [toStr appendFormat:@"%@}", lineIndent];
  1401. lineEnding = @"";
  1402. break;
  1403. }
  1404. } // switch(fieldDataType)
  1405. // End the line.
  1406. [toStr appendFormat:@"%@\n", lineEnding];
  1407. } // for(count)
  1408. }
  1409. static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
  1410. NSArray *activeExtensions,
  1411. GPBExtensionRange range,
  1412. NSMutableString *toStr,
  1413. NSString *lineIndent) {
  1414. uint32_t start = range.start;
  1415. uint32_t end = range.end;
  1416. for (GPBExtensionDescriptor *extension in activeExtensions) {
  1417. uint32_t fieldNumber = extension.fieldNumber;
  1418. if (fieldNumber < start) {
  1419. // Not there yet.
  1420. continue;
  1421. }
  1422. if (fieldNumber > end) {
  1423. // Done.
  1424. break;
  1425. }
  1426. id rawExtValue = [message getExtension:extension];
  1427. BOOL isRepeated = extension.isRepeated;
  1428. NSUInteger numValues = 1;
  1429. NSString *lineEnding = @"";
  1430. if (isRepeated) {
  1431. numValues = [(NSArray *)rawExtValue count];
  1432. }
  1433. NSString *singletonName = extension.singletonName;
  1434. if (numValues == 1) {
  1435. lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName];
  1436. } else {
  1437. [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
  1438. }
  1439. GPBDataType extDataType = extension.dataType;
  1440. for (NSUInteger j = 0; j < numValues; ++j) {
  1441. id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
  1442. // Start the line.
  1443. [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
  1444. (GPBDataTypeIsMessage(extDataType) ? "" : ":")];
  1445. // The value.
  1446. switch (extDataType) {
  1447. #define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \
  1448. case GPBDataType##GPBDATATYPE: { \
  1449. CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \
  1450. [toStr appendFormat:__VA_ARGS__, v]; \
  1451. break; \
  1452. }
  1453. FIELD_CASE(Int32, int32_t, intValue, @"%d")
  1454. FIELD_CASE(SInt32, int32_t, intValue, @"%d")
  1455. FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
  1456. FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
  1457. FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
  1458. FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
  1459. FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
  1460. FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
  1461. FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
  1462. FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
  1463. FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
  1464. FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
  1465. // TODO: Add a comment with the enum name from enum descriptors
  1466. // (might not be real value, so leave it as a comment, ObjC compiler
  1467. // name mangles differently). Doesn't look like we actually generate
  1468. // an enum descriptor reference like we do for normal fields, so this
  1469. // will take a compiler change.
  1470. FIELD_CASE(Enum, int32_t, intValue, @"%d")
  1471. #undef FIELD_CASE
  1472. case GPBDataTypeBool:
  1473. [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
  1474. : @"false")];
  1475. break;
  1476. case GPBDataTypeString:
  1477. AppendStringEscaped(curValue, toStr);
  1478. break;
  1479. case GPBDataTypeBytes:
  1480. AppendBufferAsString((NSData *)curValue, toStr);
  1481. break;
  1482. case GPBDataTypeGroup:
  1483. case GPBDataTypeMessage: {
  1484. [toStr appendFormat:@"{%@\n", lineEnding];
  1485. NSString *subIndent = [lineIndent stringByAppendingString:@" "];
  1486. AppendTextFormatForMessage(curValue, toStr, subIndent);
  1487. [toStr appendFormat:@"%@}", lineIndent];
  1488. lineEnding = @"";
  1489. break;
  1490. }
  1491. } // switch(extDataType)
  1492. } // for(numValues)
  1493. // End the line.
  1494. [toStr appendFormat:@"%@\n", lineEnding];
  1495. } // for..in(activeExtensions)
  1496. }
  1497. static void AppendTextFormatForMessage(GPBMessage *message,
  1498. NSMutableString *toStr,
  1499. NSString *lineIndent) {
  1500. GPBDescriptor *descriptor = [message descriptor];
  1501. NSArray *fieldsArray = descriptor->fields_;
  1502. NSUInteger fieldCount = fieldsArray.count;
  1503. const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
  1504. NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
  1505. NSArray *activeExtensions = [[message extensionsCurrentlySet]
  1506. sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
  1507. for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
  1508. if (i == fieldCount) {
  1509. AppendTextFormatForMessageExtensionRange(
  1510. message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
  1511. } else if (j == extensionRangesCount ||
  1512. GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
  1513. AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
  1514. lineIndent);
  1515. } else {
  1516. AppendTextFormatForMessageExtensionRange(
  1517. message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
  1518. }
  1519. }
  1520. NSString *unknownFieldsStr =
  1521. GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
  1522. if ([unknownFieldsStr length] > 0) {
  1523. [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
  1524. [toStr appendString:unknownFieldsStr];
  1525. }
  1526. }
  1527. NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
  1528. if (message == nil) return @"";
  1529. if (lineIndent == nil) lineIndent = @"";
  1530. NSMutableString *buildString = [NSMutableString string];
  1531. AppendTextFormatForMessage(message, buildString, lineIndent);
  1532. return buildString;
  1533. }
  1534. NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
  1535. NSString *lineIndent) {
  1536. if (unknownSet == nil) return @"";
  1537. if (lineIndent == nil) lineIndent = @"";
  1538. NSMutableString *result = [NSMutableString string];
  1539. for (GPBUnknownField *field in [unknownSet sortedFields]) {
  1540. int32_t fieldNumber = [field number];
  1541. #define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \
  1542. [field.PROPNAME \
  1543. enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \
  1544. _Pragma("unused(idx, stop)"); \
  1545. [result \
  1546. appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
  1547. }];
  1548. PRINT_LOOP(varintList, uint64_t, %llu);
  1549. PRINT_LOOP(fixed32List, uint32_t, 0x%X);
  1550. PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
  1551. #undef PRINT_LOOP
  1552. // NOTE: C++ version of TextFormat tries to parse this as a message
  1553. // and print that if it succeeds.
  1554. for (NSData *data in field.lengthDelimitedList) {
  1555. [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
  1556. AppendBufferAsString(data, result);
  1557. [result appendString:@"\n"];
  1558. }
  1559. for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
  1560. [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
  1561. NSString *subIndent = [lineIndent stringByAppendingString:@" "];
  1562. NSString *subUnknwonSetStr =
  1563. GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
  1564. [result appendString:subUnknwonSetStr];
  1565. [result appendFormat:@"%@}\n", lineIndent];
  1566. }
  1567. }
  1568. return result;
  1569. }
  1570. // Helpers to decode a varint. Not using GPBCodedInputStream version because
  1571. // that needs a state object, and we don't want to create an input stream out
  1572. // of the data.
  1573. GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) {
  1574. int8_t result = *((int8_t *)(*data));
  1575. ++(*data);
  1576. return result;
  1577. }
  1578. static int32_t ReadRawVarint32FromData(const uint8_t **data) {
  1579. int8_t tmp = ReadRawByteFromData(data);
  1580. if (tmp >= 0) {
  1581. return tmp;
  1582. }
  1583. int32_t result = tmp & 0x7f;
  1584. if ((tmp = ReadRawByteFromData(data)) >= 0) {
  1585. result |= tmp << 7;
  1586. } else {
  1587. result |= (tmp & 0x7f) << 7;
  1588. if ((tmp = ReadRawByteFromData(data)) >= 0) {
  1589. result |= tmp << 14;
  1590. } else {
  1591. result |= (tmp & 0x7f) << 14;
  1592. if ((tmp = ReadRawByteFromData(data)) >= 0) {
  1593. result |= tmp << 21;
  1594. } else {
  1595. result |= (tmp & 0x7f) << 21;
  1596. result |= (tmp = ReadRawByteFromData(data)) << 28;
  1597. if (tmp < 0) {
  1598. // Discard upper 32 bits.
  1599. for (int i = 0; i < 5; i++) {
  1600. if (ReadRawByteFromData(data) >= 0) {
  1601. return result;
  1602. }
  1603. }
  1604. [NSException raise:NSParseErrorException
  1605. format:@"Unable to read varint32"];
  1606. }
  1607. }
  1608. }
  1609. }
  1610. return result;
  1611. }
  1612. NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
  1613. NSString *inputStr) {
  1614. // decodData form:
  1615. // varint32: num entries
  1616. // for each entry:
  1617. // varint32: key
  1618. // bytes*: decode data
  1619. //
  1620. // decode data one of two forms:
  1621. // 1: a \0 followed by the string followed by an \0
  1622. // 2: bytecodes to transform an input into the right thing, ending with \0
  1623. //
  1624. // the bytes codes are of the form:
  1625. // 0xabbccccc
  1626. // 0x0 (all zeros), end.
  1627. // a - if set, add an underscore
  1628. // bb - 00 ccccc bytes as is
  1629. // bb - 10 ccccc upper first, as is on rest, ccccc byte total
  1630. // bb - 01 ccccc lower first, as is on rest, ccccc byte total
  1631. // bb - 11 ccccc all upper, ccccc byte total
  1632. if (!decodeData || !inputStr) {
  1633. return nil;
  1634. }
  1635. // Find key
  1636. const uint8_t *scan = decodeData;
  1637. int32_t numEntries = ReadRawVarint32FromData(&scan);
  1638. BOOL foundKey = NO;
  1639. while (!foundKey && (numEntries > 0)) {
  1640. --numEntries;
  1641. int32_t dataKey = ReadRawVarint32FromData(&scan);
  1642. if (dataKey == key) {
  1643. foundKey = YES;
  1644. } else {
  1645. // If it is a inlined string, it will start with \0; if it is bytecode it
  1646. // will start with a code. So advance one (skipping the inline string
  1647. // marker), and then loop until reaching the end marker (\0).
  1648. ++scan;
  1649. while (*scan != 0) ++scan;
  1650. // Now move past the end marker.
  1651. ++scan;
  1652. }
  1653. }
  1654. if (!foundKey) {
  1655. return nil;
  1656. }
  1657. // Decode
  1658. if (*scan == 0) {
  1659. // Inline string. Move over the marker, and NSString can take it as
  1660. // UTF8.
  1661. ++scan;
  1662. NSString *result = [NSString stringWithUTF8String:(const char *)scan];
  1663. return result;
  1664. }
  1665. NSMutableString *result =
  1666. [NSMutableString stringWithCapacity:[inputStr length]];
  1667. const uint8_t kAddUnderscore = 0b10000000;
  1668. const uint8_t kOpMask = 0b01100000;
  1669. // const uint8_t kOpAsIs = 0b00000000;
  1670. const uint8_t kOpFirstUpper = 0b01000000;
  1671. const uint8_t kOpFirstLower = 0b00100000;
  1672. const uint8_t kOpAllUpper = 0b01100000;
  1673. const uint8_t kSegmentLenMask = 0b00011111;
  1674. NSInteger i = 0;
  1675. for (; *scan != 0; ++scan) {
  1676. if (*scan & kAddUnderscore) {
  1677. [result appendString:@"_"];
  1678. }
  1679. int segmentLen = *scan & kSegmentLenMask;
  1680. uint8_t decodeOp = *scan & kOpMask;
  1681. // Do op specific handling of the first character.
  1682. if (decodeOp == kOpFirstUpper) {
  1683. unichar c = [inputStr characterAtIndex:i];
  1684. [result appendFormat:@"%c", toupper((char)c)];
  1685. ++i;
  1686. --segmentLen;
  1687. } else if (decodeOp == kOpFirstLower) {
  1688. unichar c = [inputStr characterAtIndex:i];
  1689. [result appendFormat:@"%c", tolower((char)c)];
  1690. ++i;
  1691. --segmentLen;
  1692. }
  1693. // else op == kOpAsIs || op == kOpAllUpper
  1694. // Now pull over the rest of the length for this segment.
  1695. for (int x = 0; x < segmentLen; ++x) {
  1696. unichar c = [inputStr characterAtIndex:(i + x)];
  1697. if (decodeOp == kOpAllUpper) {
  1698. [result appendFormat:@"%c", toupper((char)c)];
  1699. } else {
  1700. [result appendFormat:@"%C", c];
  1701. }
  1702. }
  1703. i += segmentLen;
  1704. }
  1705. return result;
  1706. }
  1707. #pragma clang diagnostic pop
  1708. BOOL GPBClassHasSel(Class aClass, SEL sel) {
  1709. // NOTE: We have to use class_copyMethodList, all other runtime method
  1710. // lookups actually also resolve the method implementation and this
  1711. // is called from within those methods.
  1712. BOOL result = NO;
  1713. unsigned int methodCount = 0;
  1714. Method *methodList = class_copyMethodList(aClass, &methodCount);
  1715. for (unsigned int i = 0; i < methodCount; ++i) {
  1716. SEL methodSelector = method_getName(methodList[i]);
  1717. if (methodSelector == sel) {
  1718. result = YES;
  1719. break;
  1720. }
  1721. }
  1722. free(methodList);
  1723. return result;
  1724. }
  1725. #pragma mark - GPBMessageSignatureProtocol
  1726. // A series of selectors that are used solely to get @encoding values
  1727. // for them by the dynamic protobuf runtime code. An object using the protocol
  1728. // needs to be declared for the protocol to be valid at runtime.
  1729. @interface GPBMessageSignatureProtocol : NSObject<GPBMessageSignatureProtocol>
  1730. @end
  1731. @implementation GPBMessageSignatureProtocol
  1732. @end