GPBExtensionField.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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 "GPBExtensionField_PackagePrivate.h"
  31. #import <objc/runtime.h>
  32. #import "GPBCodedInputStream_PackagePrivate.h"
  33. #import "GPBCodedOutputStream.h"
  34. #import "GPBDescriptor_PackagePrivate.h"
  35. #import "GPBMessage_PackagePrivate.h"
  36. #import "GPBUtilities_PackagePrivate.h"
  37. GPB_INLINE size_t TypeSize(GPBType type) {
  38. switch (type) {
  39. case GPBTypeBool:
  40. return 1;
  41. case GPBTypeFixed32:
  42. case GPBTypeSFixed32:
  43. case GPBTypeFloat:
  44. return 4;
  45. case GPBTypeFixed64:
  46. case GPBTypeSFixed64:
  47. case GPBTypeDouble:
  48. return 8;
  49. default:
  50. return 0;
  51. }
  52. }
  53. GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) {
  54. return (description->options & GPBExtensionRepeated) != 0;
  55. }
  56. GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) {
  57. return (description->options & GPBExtensionPacked) != 0;
  58. }
  59. GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) {
  60. return (description->options & GPBExtensionSetWireFormat) != 0;
  61. }
  62. static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) {
  63. #define FIELD_CASE(TYPE, ACCESSOR) \
  64. case GPBType##TYPE: \
  65. return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
  66. #define FIELD_CASE2(TYPE) \
  67. case GPBType##TYPE: \
  68. return GPBCompute##TYPE##SizeNoTag(object);
  69. switch (type) {
  70. FIELD_CASE(Bool, boolValue)
  71. FIELD_CASE(Float, floatValue)
  72. FIELD_CASE(Double, doubleValue)
  73. FIELD_CASE(Int32, intValue)
  74. FIELD_CASE(SFixed32, intValue)
  75. FIELD_CASE(SInt32, intValue)
  76. FIELD_CASE(Enum, intValue)
  77. FIELD_CASE(Int64, longLongValue)
  78. FIELD_CASE(SInt64, longLongValue)
  79. FIELD_CASE(SFixed64, longLongValue)
  80. FIELD_CASE(UInt32, unsignedIntValue)
  81. FIELD_CASE(Fixed32, unsignedIntValue)
  82. FIELD_CASE(UInt64, unsignedLongLongValue)
  83. FIELD_CASE(Fixed64, unsignedLongLongValue)
  84. FIELD_CASE2(Data)
  85. FIELD_CASE2(String)
  86. FIELD_CASE2(Message)
  87. FIELD_CASE2(Group)
  88. }
  89. #undef FIELD_CASE
  90. #undef FIELD_CASE2
  91. }
  92. static size_t ComputeSerializedSizeIncludingTagOfObject(
  93. GPBExtensionDescription *description, id object) {
  94. #define FIELD_CASE(TYPE, ACCESSOR) \
  95. case GPBType##TYPE: \
  96. return GPBCompute##TYPE##Size(description->fieldNumber, \
  97. [(NSNumber *)object ACCESSOR]);
  98. #define FIELD_CASE2(TYPE) \
  99. case GPBType##TYPE: \
  100. return GPBCompute##TYPE##Size(description->fieldNumber, object);
  101. switch (description->type) {
  102. FIELD_CASE(Bool, boolValue)
  103. FIELD_CASE(Float, floatValue)
  104. FIELD_CASE(Double, doubleValue)
  105. FIELD_CASE(Int32, intValue)
  106. FIELD_CASE(SFixed32, intValue)
  107. FIELD_CASE(SInt32, intValue)
  108. FIELD_CASE(Enum, intValue)
  109. FIELD_CASE(Int64, longLongValue)
  110. FIELD_CASE(SInt64, longLongValue)
  111. FIELD_CASE(SFixed64, longLongValue)
  112. FIELD_CASE(UInt32, unsignedIntValue)
  113. FIELD_CASE(Fixed32, unsignedIntValue)
  114. FIELD_CASE(UInt64, unsignedLongLongValue)
  115. FIELD_CASE(Fixed64, unsignedLongLongValue)
  116. FIELD_CASE2(Data)
  117. FIELD_CASE2(String)
  118. FIELD_CASE2(Group)
  119. case GPBTypeMessage:
  120. if (ExtensionIsWireFormat(description)) {
  121. return GPBComputeMessageSetExtensionSize(description->fieldNumber,
  122. object);
  123. } else {
  124. return GPBComputeMessageSize(description->fieldNumber, object);
  125. }
  126. }
  127. #undef FIELD_CASE
  128. #undef FIELD_CASE2
  129. }
  130. static size_t ComputeSerializedSizeIncludingTagOfArray(
  131. GPBExtensionDescription *description, NSArray *values) {
  132. if (ExtensionIsPacked(description)) {
  133. size_t size = 0;
  134. size_t typeSize = TypeSize(description->type);
  135. if (typeSize != 0) {
  136. size = values.count * typeSize;
  137. } else {
  138. for (id value in values) {
  139. size += ComputePBSerializedSizeNoTagOfObject(description->type, value);
  140. }
  141. }
  142. return size + GPBComputeTagSize(description->fieldNumber) +
  143. GPBComputeRawVarint32SizeForInteger(size);
  144. } else {
  145. size_t size = 0;
  146. for (id value in values) {
  147. size += ComputeSerializedSizeIncludingTagOfObject(description, value);
  148. }
  149. return size;
  150. }
  151. }
  152. static void WriteObjectIncludingTagToCodedOutputStream(
  153. id object, GPBExtensionDescription *description,
  154. GPBCodedOutputStream *output) {
  155. #define FIELD_CASE(TYPE, ACCESSOR) \
  156. case GPBType##TYPE: \
  157. [output write##TYPE:description->fieldNumber \
  158. value:[(NSNumber *)object ACCESSOR]]; \
  159. return;
  160. #define FIELD_CASE2(TYPE) \
  161. case GPBType##TYPE: \
  162. [output write##TYPE:description->fieldNumber value:object]; \
  163. return;
  164. switch (description->type) {
  165. FIELD_CASE(Bool, boolValue)
  166. FIELD_CASE(Float, floatValue)
  167. FIELD_CASE(Double, doubleValue)
  168. FIELD_CASE(Int32, intValue)
  169. FIELD_CASE(SFixed32, intValue)
  170. FIELD_CASE(SInt32, intValue)
  171. FIELD_CASE(Enum, intValue)
  172. FIELD_CASE(Int64, longLongValue)
  173. FIELD_CASE(SInt64, longLongValue)
  174. FIELD_CASE(SFixed64, longLongValue)
  175. FIELD_CASE(UInt32, unsignedIntValue)
  176. FIELD_CASE(Fixed32, unsignedIntValue)
  177. FIELD_CASE(UInt64, unsignedLongLongValue)
  178. FIELD_CASE(Fixed64, unsignedLongLongValue)
  179. FIELD_CASE2(Data)
  180. FIELD_CASE2(String)
  181. FIELD_CASE2(Group)
  182. case GPBTypeMessage:
  183. if (ExtensionIsWireFormat(description)) {
  184. [output writeMessageSetExtension:description->fieldNumber value:object];
  185. } else {
  186. [output writeMessage:description->fieldNumber value:object];
  187. }
  188. return;
  189. }
  190. #undef FIELD_CASE
  191. #undef FIELD_CASE2
  192. }
  193. static void WriteObjectNoTagToCodedOutputStream(
  194. id object, GPBExtensionDescription *description,
  195. GPBCodedOutputStream *output) {
  196. #define FIELD_CASE(TYPE, ACCESSOR) \
  197. case GPBType##TYPE: \
  198. [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
  199. return;
  200. #define FIELD_CASE2(TYPE) \
  201. case GPBType##TYPE: \
  202. [output write##TYPE##NoTag:object]; \
  203. return;
  204. switch (description->type) {
  205. FIELD_CASE(Bool, boolValue)
  206. FIELD_CASE(Float, floatValue)
  207. FIELD_CASE(Double, doubleValue)
  208. FIELD_CASE(Int32, intValue)
  209. FIELD_CASE(SFixed32, intValue)
  210. FIELD_CASE(SInt32, intValue)
  211. FIELD_CASE(Enum, intValue)
  212. FIELD_CASE(Int64, longLongValue)
  213. FIELD_CASE(SInt64, longLongValue)
  214. FIELD_CASE(SFixed64, longLongValue)
  215. FIELD_CASE(UInt32, unsignedIntValue)
  216. FIELD_CASE(Fixed32, unsignedIntValue)
  217. FIELD_CASE(UInt64, unsignedLongLongValue)
  218. FIELD_CASE(Fixed64, unsignedLongLongValue)
  219. FIELD_CASE2(Data)
  220. FIELD_CASE2(String)
  221. FIELD_CASE2(Message)
  222. case GPBTypeGroup:
  223. [output writeGroupNoTag:description->fieldNumber value:object];
  224. return;
  225. }
  226. #undef FIELD_CASE
  227. #undef FIELD_CASE2
  228. }
  229. static void WriteArrayIncludingTagsToCodedOutputStream(
  230. NSArray *values, GPBExtensionDescription *description,
  231. GPBCodedOutputStream *output) {
  232. if (ExtensionIsPacked(description)) {
  233. [output writeTag:description->fieldNumber
  234. format:GPBWireFormatLengthDelimited];
  235. size_t dataSize = 0;
  236. size_t typeSize = TypeSize(description->type);
  237. if (typeSize != 0) {
  238. dataSize = values.count * typeSize;
  239. } else {
  240. for (id value in values) {
  241. dataSize +=
  242. ComputePBSerializedSizeNoTagOfObject(description->type, value);
  243. }
  244. }
  245. [output writeRawVarintSizeTAs32:dataSize];
  246. for (id value in values) {
  247. WriteObjectNoTagToCodedOutputStream(value, description, output);
  248. }
  249. } else {
  250. for (id value in values) {
  251. WriteObjectIncludingTagToCodedOutputStream(value, description, output);
  252. }
  253. }
  254. }
  255. @implementation GPBExtensionField {
  256. GPBExtensionDescription *description_;
  257. GPBExtensionDescriptor *descriptor_;
  258. GPBValue defaultValue_;
  259. }
  260. @synthesize containingType = containingType_;
  261. @synthesize descriptor = descriptor_;
  262. - (instancetype)init {
  263. // Throw an exception if people attempt to not use the designated initializer.
  264. self = [super init];
  265. if (self != nil) {
  266. [self doesNotRecognizeSelector:_cmd];
  267. self = nil;
  268. }
  269. return self;
  270. }
  271. - (instancetype)initWithDescription:(GPBExtensionDescription *)description {
  272. if ((self = [super init])) {
  273. description_ = description;
  274. if (description->extendedClass) {
  275. Class containingClass = objc_lookUpClass(description->extendedClass);
  276. NSAssert1(containingClass, @"Class %s not defined",
  277. description->extendedClass);
  278. containingType_ = [containingClass descriptor];
  279. }
  280. #if DEBUG
  281. const char *className = description->messageOrGroupClassName;
  282. if (className) {
  283. NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined",
  284. className);
  285. }
  286. #endif
  287. descriptor_ = [[GPBExtensionDescriptor alloc]
  288. initWithExtensionDescription:description];
  289. GPBType type = description_->type;
  290. if (type == GPBTypeData) {
  291. // Data stored as a length prefixed c-string in descriptor records.
  292. const uint8_t *bytes =
  293. (const uint8_t *)description->defaultValue.valueData;
  294. if (bytes) {
  295. uint32_t length = *((uint32_t *)bytes);
  296. // The length is stored in network byte order.
  297. length = ntohl(length);
  298. bytes += sizeof(length);
  299. defaultValue_.valueData =
  300. [[NSData alloc] initWithBytes:bytes length:length];
  301. }
  302. } else if (type == GPBTypeMessage || type == GPBTypeGroup) {
  303. // The default is looked up in -defaultValue instead since extensions
  304. // aren't
  305. // common, we avoid the hit startup hit and it avoid initialization order
  306. // issues.
  307. } else {
  308. defaultValue_ = description->defaultValue;
  309. }
  310. }
  311. return self;
  312. }
  313. - (void)dealloc {
  314. if ((description_->type == GPBTypeData) &&
  315. !ExtensionIsRepeated(description_)) {
  316. [defaultValue_.valueData release];
  317. }
  318. [descriptor_ release];
  319. [super dealloc];
  320. }
  321. - (NSString *)description {
  322. return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@",
  323. [self class], self, self.fieldNumber,
  324. self.containingType];
  325. }
  326. - (id)copyWithZone:(NSZone *)__unused zone {
  327. return [self retain];
  328. }
  329. #pragma mark Properties
  330. - (int32_t)fieldNumber {
  331. return description_->fieldNumber;
  332. }
  333. - (GPBWireFormat)wireType {
  334. return GPBWireFormatForType(description_->type,
  335. ExtensionIsPacked(description_));
  336. }
  337. - (BOOL)isRepeated {
  338. return ExtensionIsRepeated(description_);
  339. }
  340. - (id)defaultValue {
  341. if (ExtensionIsRepeated(description_)) {
  342. return nil;
  343. }
  344. switch (description_->type) {
  345. case GPBTypeBool:
  346. return @(defaultValue_.valueBool);
  347. case GPBTypeFloat:
  348. return @(defaultValue_.valueFloat);
  349. case GPBTypeDouble:
  350. return @(defaultValue_.valueDouble);
  351. case GPBTypeInt32:
  352. case GPBTypeSInt32:
  353. case GPBTypeEnum:
  354. case GPBTypeSFixed32:
  355. return @(defaultValue_.valueInt32);
  356. case GPBTypeInt64:
  357. case GPBTypeSInt64:
  358. case GPBTypeSFixed64:
  359. return @(defaultValue_.valueInt64);
  360. case GPBTypeUInt32:
  361. case GPBTypeFixed32:
  362. return @(defaultValue_.valueUInt32);
  363. case GPBTypeUInt64:
  364. case GPBTypeFixed64:
  365. return @(defaultValue_.valueUInt64);
  366. case GPBTypeData:
  367. // Like message fields, the default is zero length data.
  368. return (defaultValue_.valueData ? defaultValue_.valueData
  369. : GPBEmptyNSData());
  370. case GPBTypeString:
  371. // Like message fields, the default is zero length string.
  372. return (defaultValue_.valueString ? defaultValue_.valueString : @"");
  373. case GPBTypeGroup:
  374. case GPBTypeMessage:
  375. NSAssert(0, @"Shouldn't get here");
  376. return nil;
  377. }
  378. }
  379. #pragma mark Internals
  380. - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
  381. extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
  382. message:(GPBMessage *)message {
  383. GPBCodedInputStreamState *state = &input->state_;
  384. if (ExtensionIsPacked(description_)) {
  385. int32_t length = GPBCodedInputStreamReadInt32(state);
  386. size_t limit = GPBCodedInputStreamPushLimit(state, length);
  387. while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
  388. id value = [self newSingleValueFromCodedInputStream:input
  389. extensionRegistry:extensionRegistry
  390. existingValue:nil];
  391. [message addExtension:self value:value];
  392. [value release];
  393. }
  394. GPBCodedInputStreamPopLimit(state, limit);
  395. } else {
  396. id existingValue = nil;
  397. BOOL isRepeated = ExtensionIsRepeated(description_);
  398. if (!isRepeated && GPBTypeIsMessage(description_->type)) {
  399. existingValue = [message getExistingExtension:self];
  400. }
  401. id value = [self newSingleValueFromCodedInputStream:input
  402. extensionRegistry:extensionRegistry
  403. existingValue:existingValue];
  404. if (isRepeated) {
  405. [message addExtension:self value:value];
  406. } else {
  407. [message setExtension:self value:value];
  408. }
  409. [value release];
  410. }
  411. }
  412. - (void)writeValue:(id)value
  413. includingTagToCodedOutputStream:(GPBCodedOutputStream *)output {
  414. if (ExtensionIsRepeated(description_)) {
  415. WriteArrayIncludingTagsToCodedOutputStream(value, description_, output);
  416. } else {
  417. WriteObjectIncludingTagToCodedOutputStream(value, description_, output);
  418. }
  419. }
  420. - (size_t)computeSerializedSizeIncludingTag:(id)value {
  421. if (ExtensionIsRepeated(description_)) {
  422. return ComputeSerializedSizeIncludingTagOfArray(description_, value);
  423. } else {
  424. return ComputeSerializedSizeIncludingTagOfObject(description_, value);
  425. }
  426. }
  427. // Note that this returns a retained value intentionally.
  428. - (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input
  429. extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
  430. existingValue:(GPBMessage *)existingValue {
  431. GPBCodedInputStreamState *state = &input->state_;
  432. switch (description_->type) {
  433. case GPBTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
  434. case GPBTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
  435. case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
  436. case GPBTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
  437. case GPBTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
  438. case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
  439. case GPBTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
  440. case GPBTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
  441. case GPBTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
  442. case GPBTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
  443. case GPBTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
  444. case GPBTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
  445. case GPBTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
  446. case GPBTypeData: return GPBCodedInputStreamReadRetainedData(state);
  447. case GPBTypeString: return GPBCodedInputStreamReadRetainedString(state);
  448. case GPBTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
  449. case GPBTypeGroup:
  450. case GPBTypeMessage: {
  451. GPBMessage *message;
  452. if (existingValue) {
  453. message = [existingValue retain];
  454. } else {
  455. GPBDescriptor *decriptor = [descriptor_.msgClass descriptor];
  456. message = [[decriptor.messageClass alloc] init];
  457. }
  458. if (description_->type == GPBTypeGroup) {
  459. [input readGroup:description_->fieldNumber
  460. message:message
  461. extensionRegistry:extensionRegistry];
  462. } else {
  463. // description_->type == GPBTypeMessage
  464. if (ExtensionIsWireFormat(description_)) {
  465. // For MessageSet fields the message length will have already been
  466. // read.
  467. [message mergeFromCodedInputStream:input
  468. extensionRegistry:extensionRegistry];
  469. } else {
  470. [input readMessage:message extensionRegistry:extensionRegistry];
  471. }
  472. }
  473. return message;
  474. }
  475. }
  476. return nil;
  477. }
  478. - (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other {
  479. int32_t selfNumber = description_->fieldNumber;
  480. int32_t otherNumber = other->description_->fieldNumber;
  481. if (selfNumber < otherNumber) {
  482. return NSOrderedAscending;
  483. } else if (selfNumber == otherNumber) {
  484. return NSOrderedSame;
  485. } else {
  486. return NSOrderedDescending;
  487. }
  488. }
  489. @end