123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // https://developers.google.com/protocol-buffers/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #import "GPBExtensionField_PackagePrivate.h"
- #import <objc/runtime.h>
- #import "GPBCodedInputStream_PackagePrivate.h"
- #import "GPBCodedOutputStream.h"
- #import "GPBDescriptor_PackagePrivate.h"
- #import "GPBMessage_PackagePrivate.h"
- #import "GPBUtilities_PackagePrivate.h"
- GPB_INLINE size_t TypeSize(GPBType type) {
- switch (type) {
- case GPBTypeBool:
- return 1;
- case GPBTypeFixed32:
- case GPBTypeSFixed32:
- case GPBTypeFloat:
- return 4;
- case GPBTypeFixed64:
- case GPBTypeSFixed64:
- case GPBTypeDouble:
- return 8;
- default:
- return 0;
- }
- }
- GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) {
- return (description->options & GPBExtensionRepeated) != 0;
- }
- GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) {
- return (description->options & GPBExtensionPacked) != 0;
- }
- GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) {
- return (description->options & GPBExtensionSetWireFormat) != 0;
- }
- static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) {
- #define FIELD_CASE(TYPE, ACCESSOR) \
- case GPBType##TYPE: \
- return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
- #define FIELD_CASE2(TYPE) \
- case GPBType##TYPE: \
- return GPBCompute##TYPE##SizeNoTag(object);
- switch (type) {
- FIELD_CASE(Bool, boolValue)
- FIELD_CASE(Float, floatValue)
- FIELD_CASE(Double, doubleValue)
- FIELD_CASE(Int32, intValue)
- FIELD_CASE(SFixed32, intValue)
- FIELD_CASE(SInt32, intValue)
- FIELD_CASE(Enum, intValue)
- FIELD_CASE(Int64, longLongValue)
- FIELD_CASE(SInt64, longLongValue)
- FIELD_CASE(SFixed64, longLongValue)
- FIELD_CASE(UInt32, unsignedIntValue)
- FIELD_CASE(Fixed32, unsignedIntValue)
- FIELD_CASE(UInt64, unsignedLongLongValue)
- FIELD_CASE(Fixed64, unsignedLongLongValue)
- FIELD_CASE2(Data)
- FIELD_CASE2(String)
- FIELD_CASE2(Message)
- FIELD_CASE2(Group)
- }
- #undef FIELD_CASE
- #undef FIELD_CASE2
- }
- static size_t ComputeSerializedSizeIncludingTagOfObject(
- GPBExtensionDescription *description, id object) {
- #define FIELD_CASE(TYPE, ACCESSOR) \
- case GPBType##TYPE: \
- return GPBCompute##TYPE##Size(description->fieldNumber, \
- [(NSNumber *)object ACCESSOR]);
- #define FIELD_CASE2(TYPE) \
- case GPBType##TYPE: \
- return GPBCompute##TYPE##Size(description->fieldNumber, object);
- switch (description->type) {
- FIELD_CASE(Bool, boolValue)
- FIELD_CASE(Float, floatValue)
- FIELD_CASE(Double, doubleValue)
- FIELD_CASE(Int32, intValue)
- FIELD_CASE(SFixed32, intValue)
- FIELD_CASE(SInt32, intValue)
- FIELD_CASE(Enum, intValue)
- FIELD_CASE(Int64, longLongValue)
- FIELD_CASE(SInt64, longLongValue)
- FIELD_CASE(SFixed64, longLongValue)
- FIELD_CASE(UInt32, unsignedIntValue)
- FIELD_CASE(Fixed32, unsignedIntValue)
- FIELD_CASE(UInt64, unsignedLongLongValue)
- FIELD_CASE(Fixed64, unsignedLongLongValue)
- FIELD_CASE2(Data)
- FIELD_CASE2(String)
- FIELD_CASE2(Group)
- case GPBTypeMessage:
- if (ExtensionIsWireFormat(description)) {
- return GPBComputeMessageSetExtensionSize(description->fieldNumber,
- object);
- } else {
- return GPBComputeMessageSize(description->fieldNumber, object);
- }
- }
- #undef FIELD_CASE
- #undef FIELD_CASE2
- }
- static size_t ComputeSerializedSizeIncludingTagOfArray(
- GPBExtensionDescription *description, NSArray *values) {
- if (ExtensionIsPacked(description)) {
- size_t size = 0;
- size_t typeSize = TypeSize(description->type);
- if (typeSize != 0) {
- size = values.count * typeSize;
- } else {
- for (id value in values) {
- size += ComputePBSerializedSizeNoTagOfObject(description->type, value);
- }
- }
- return size + GPBComputeTagSize(description->fieldNumber) +
- GPBComputeRawVarint32SizeForInteger(size);
- } else {
- size_t size = 0;
- for (id value in values) {
- size += ComputeSerializedSizeIncludingTagOfObject(description, value);
- }
- return size;
- }
- }
- static void WriteObjectIncludingTagToCodedOutputStream(
- id object, GPBExtensionDescription *description,
- GPBCodedOutputStream *output) {
- #define FIELD_CASE(TYPE, ACCESSOR) \
- case GPBType##TYPE: \
- [output write##TYPE:description->fieldNumber \
- value:[(NSNumber *)object ACCESSOR]]; \
- return;
- #define FIELD_CASE2(TYPE) \
- case GPBType##TYPE: \
- [output write##TYPE:description->fieldNumber value:object]; \
- return;
- switch (description->type) {
- FIELD_CASE(Bool, boolValue)
- FIELD_CASE(Float, floatValue)
- FIELD_CASE(Double, doubleValue)
- FIELD_CASE(Int32, intValue)
- FIELD_CASE(SFixed32, intValue)
- FIELD_CASE(SInt32, intValue)
- FIELD_CASE(Enum, intValue)
- FIELD_CASE(Int64, longLongValue)
- FIELD_CASE(SInt64, longLongValue)
- FIELD_CASE(SFixed64, longLongValue)
- FIELD_CASE(UInt32, unsignedIntValue)
- FIELD_CASE(Fixed32, unsignedIntValue)
- FIELD_CASE(UInt64, unsignedLongLongValue)
- FIELD_CASE(Fixed64, unsignedLongLongValue)
- FIELD_CASE2(Data)
- FIELD_CASE2(String)
- FIELD_CASE2(Group)
- case GPBTypeMessage:
- if (ExtensionIsWireFormat(description)) {
- [output writeMessageSetExtension:description->fieldNumber value:object];
- } else {
- [output writeMessage:description->fieldNumber value:object];
- }
- return;
- }
- #undef FIELD_CASE
- #undef FIELD_CASE2
- }
- static void WriteObjectNoTagToCodedOutputStream(
- id object, GPBExtensionDescription *description,
- GPBCodedOutputStream *output) {
- #define FIELD_CASE(TYPE, ACCESSOR) \
- case GPBType##TYPE: \
- [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
- return;
- #define FIELD_CASE2(TYPE) \
- case GPBType##TYPE: \
- [output write##TYPE##NoTag:object]; \
- return;
- switch (description->type) {
- FIELD_CASE(Bool, boolValue)
- FIELD_CASE(Float, floatValue)
- FIELD_CASE(Double, doubleValue)
- FIELD_CASE(Int32, intValue)
- FIELD_CASE(SFixed32, intValue)
- FIELD_CASE(SInt32, intValue)
- FIELD_CASE(Enum, intValue)
- FIELD_CASE(Int64, longLongValue)
- FIELD_CASE(SInt64, longLongValue)
- FIELD_CASE(SFixed64, longLongValue)
- FIELD_CASE(UInt32, unsignedIntValue)
- FIELD_CASE(Fixed32, unsignedIntValue)
- FIELD_CASE(UInt64, unsignedLongLongValue)
- FIELD_CASE(Fixed64, unsignedLongLongValue)
- FIELD_CASE2(Data)
- FIELD_CASE2(String)
- FIELD_CASE2(Message)
- case GPBTypeGroup:
- [output writeGroupNoTag:description->fieldNumber value:object];
- return;
- }
- #undef FIELD_CASE
- #undef FIELD_CASE2
- }
- static void WriteArrayIncludingTagsToCodedOutputStream(
- NSArray *values, GPBExtensionDescription *description,
- GPBCodedOutputStream *output) {
- if (ExtensionIsPacked(description)) {
- [output writeTag:description->fieldNumber
- format:GPBWireFormatLengthDelimited];
- size_t dataSize = 0;
- size_t typeSize = TypeSize(description->type);
- if (typeSize != 0) {
- dataSize = values.count * typeSize;
- } else {
- for (id value in values) {
- dataSize +=
- ComputePBSerializedSizeNoTagOfObject(description->type, value);
- }
- }
- [output writeRawVarintSizeTAs32:dataSize];
- for (id value in values) {
- WriteObjectNoTagToCodedOutputStream(value, description, output);
- }
- } else {
- for (id value in values) {
- WriteObjectIncludingTagToCodedOutputStream(value, description, output);
- }
- }
- }
- @implementation GPBExtensionField {
- GPBExtensionDescription *description_;
- GPBExtensionDescriptor *descriptor_;
- GPBValue defaultValue_;
- }
- @synthesize containingType = containingType_;
- @synthesize descriptor = descriptor_;
- - (instancetype)init {
- // Throw an exception if people attempt to not use the designated initializer.
- self = [super init];
- if (self != nil) {
- [self doesNotRecognizeSelector:_cmd];
- self = nil;
- }
- return self;
- }
- - (instancetype)initWithDescription:(GPBExtensionDescription *)description {
- if ((self = [super init])) {
- description_ = description;
- if (description->extendedClass) {
- Class containingClass = objc_lookUpClass(description->extendedClass);
- NSAssert1(containingClass, @"Class %s not defined",
- description->extendedClass);
- containingType_ = [containingClass descriptor];
- }
- #if DEBUG
- const char *className = description->messageOrGroupClassName;
- if (className) {
- NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined",
- className);
- }
- #endif
- descriptor_ = [[GPBExtensionDescriptor alloc]
- initWithExtensionDescription:description];
- GPBType type = description_->type;
- if (type == GPBTypeData) {
- // Data stored as a length prefixed c-string in descriptor records.
- const uint8_t *bytes =
- (const uint8_t *)description->defaultValue.valueData;
- if (bytes) {
- uint32_t length = *((uint32_t *)bytes);
- // The length is stored in network byte order.
- length = ntohl(length);
- bytes += sizeof(length);
- defaultValue_.valueData =
- [[NSData alloc] initWithBytes:bytes length:length];
- }
- } else if (type == GPBTypeMessage || type == GPBTypeGroup) {
- // The default is looked up in -defaultValue instead since extensions
- // aren't
- // common, we avoid the hit startup hit and it avoid initialization order
- // issues.
- } else {
- defaultValue_ = description->defaultValue;
- }
- }
- return self;
- }
- - (void)dealloc {
- if ((description_->type == GPBTypeData) &&
- !ExtensionIsRepeated(description_)) {
- [defaultValue_.valueData release];
- }
- [descriptor_ release];
- [super dealloc];
- }
- - (NSString *)description {
- return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@",
- [self class], self, self.fieldNumber,
- self.containingType];
- }
- - (id)copyWithZone:(NSZone *)__unused zone {
- return [self retain];
- }
- #pragma mark Properties
- - (int32_t)fieldNumber {
- return description_->fieldNumber;
- }
- - (GPBWireFormat)wireType {
- return GPBWireFormatForType(description_->type,
- ExtensionIsPacked(description_));
- }
- - (BOOL)isRepeated {
- return ExtensionIsRepeated(description_);
- }
- - (id)defaultValue {
- if (ExtensionIsRepeated(description_)) {
- return nil;
- }
- switch (description_->type) {
- case GPBTypeBool:
- return @(defaultValue_.valueBool);
- case GPBTypeFloat:
- return @(defaultValue_.valueFloat);
- case GPBTypeDouble:
- return @(defaultValue_.valueDouble);
- case GPBTypeInt32:
- case GPBTypeSInt32:
- case GPBTypeEnum:
- case GPBTypeSFixed32:
- return @(defaultValue_.valueInt32);
- case GPBTypeInt64:
- case GPBTypeSInt64:
- case GPBTypeSFixed64:
- return @(defaultValue_.valueInt64);
- case GPBTypeUInt32:
- case GPBTypeFixed32:
- return @(defaultValue_.valueUInt32);
- case GPBTypeUInt64:
- case GPBTypeFixed64:
- return @(defaultValue_.valueUInt64);
- case GPBTypeData:
- // Like message fields, the default is zero length data.
- return (defaultValue_.valueData ? defaultValue_.valueData
- : GPBEmptyNSData());
- case GPBTypeString:
- // Like message fields, the default is zero length string.
- return (defaultValue_.valueString ? defaultValue_.valueString : @"");
- case GPBTypeGroup:
- case GPBTypeMessage:
- NSAssert(0, @"Shouldn't get here");
- return nil;
- }
- }
- #pragma mark Internals
- - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
- extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
- message:(GPBMessage *)message {
- GPBCodedInputStreamState *state = &input->state_;
- if (ExtensionIsPacked(description_)) {
- int32_t length = GPBCodedInputStreamReadInt32(state);
- size_t limit = GPBCodedInputStreamPushLimit(state, length);
- while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
- id value = [self newSingleValueFromCodedInputStream:input
- extensionRegistry:extensionRegistry
- existingValue:nil];
- [message addExtension:self value:value];
- [value release];
- }
- GPBCodedInputStreamPopLimit(state, limit);
- } else {
- id existingValue = nil;
- BOOL isRepeated = ExtensionIsRepeated(description_);
- if (!isRepeated && GPBTypeIsMessage(description_->type)) {
- existingValue = [message getExistingExtension:self];
- }
- id value = [self newSingleValueFromCodedInputStream:input
- extensionRegistry:extensionRegistry
- existingValue:existingValue];
- if (isRepeated) {
- [message addExtension:self value:value];
- } else {
- [message setExtension:self value:value];
- }
- [value release];
- }
- }
- - (void)writeValue:(id)value
- includingTagToCodedOutputStream:(GPBCodedOutputStream *)output {
- if (ExtensionIsRepeated(description_)) {
- WriteArrayIncludingTagsToCodedOutputStream(value, description_, output);
- } else {
- WriteObjectIncludingTagToCodedOutputStream(value, description_, output);
- }
- }
- - (size_t)computeSerializedSizeIncludingTag:(id)value {
- if (ExtensionIsRepeated(description_)) {
- return ComputeSerializedSizeIncludingTagOfArray(description_, value);
- } else {
- return ComputeSerializedSizeIncludingTagOfObject(description_, value);
- }
- }
- // Note that this returns a retained value intentionally.
- - (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input
- extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
- existingValue:(GPBMessage *)existingValue {
- GPBCodedInputStreamState *state = &input->state_;
- switch (description_->type) {
- case GPBTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
- case GPBTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
- case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
- case GPBTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
- case GPBTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
- case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
- case GPBTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
- case GPBTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
- case GPBTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
- case GPBTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
- case GPBTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
- case GPBTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
- case GPBTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
- case GPBTypeData: return GPBCodedInputStreamReadRetainedData(state);
- case GPBTypeString: return GPBCodedInputStreamReadRetainedString(state);
- case GPBTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
- case GPBTypeGroup:
- case GPBTypeMessage: {
- GPBMessage *message;
- if (existingValue) {
- message = [existingValue retain];
- } else {
- GPBDescriptor *decriptor = [descriptor_.msgClass descriptor];
- message = [[decriptor.messageClass alloc] init];
- }
- if (description_->type == GPBTypeGroup) {
- [input readGroup:description_->fieldNumber
- message:message
- extensionRegistry:extensionRegistry];
- } else {
- // description_->type == GPBTypeMessage
- if (ExtensionIsWireFormat(description_)) {
- // For MessageSet fields the message length will have already been
- // read.
- [message mergeFromCodedInputStream:input
- extensionRegistry:extensionRegistry];
- } else {
- [input readMessage:message extensionRegistry:extensionRegistry];
- }
- }
- return message;
- }
- }
- return nil;
- }
- - (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other {
- int32_t selfNumber = description_->fieldNumber;
- int32_t otherNumber = other->description_->fieldNumber;
- if (selfNumber < otherNumber) {
- return NSOrderedAscending;
- } else if (selfNumber == otherNumber) {
- return NSOrderedSame;
- } else {
- return NSOrderedDescending;
- }
- }
- @end
|