diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc index d47e061dcb..7ebd77492f 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_enum.cc @@ -255,7 +255,7 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { "\n" "$classname$ *$classname$_values_[$count$];\n" "\n" - "ComGoogleProtobufDescriptors_EnumDescriptor" + "static ComGoogleProtobufDescriptors_EnumDescriptor" " *$classname$_descriptor_ = nil;\n" "\n" "@implementation $classname$\n" diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.cc index a1a2ff967c..89715cc8b2 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.cc @@ -178,10 +178,6 @@ void CollectForwardDeclarationsForFieldType(std::set* declarations, declarations->insert("@class ComGoogleProtobufDescriptors_EnumDescriptor"); declarations->insert("J2OBJC_CLASS_DECLARATION(" + ClassName(descriptor->enum_type()) + ")"); - declarations->insert( - "FOUNDATION_EXPORT " - "ComGoogleProtobufDescriptors_EnumDescriptor * _Nonnull " + - ClassName(descriptor->enum_type()) + "_descriptor_"); } else if (type == JAVATYPE_MESSAGE) { std::string classname = ClassName(descriptor->message_type()); declarations->insert("@class " + classname); @@ -279,7 +275,6 @@ void FieldGenerator::GenerateFieldData(io::Printer *printer) const { ); GenerateFieldDataOffset(printer); GenerateClassNameOrMapData(printer); - GenerateStaticRefs(printer); printer->Print(variables_, " .containingType = NULL,\n" // Used by extensions. " .optionsData = $options_data$,\n" @@ -295,21 +290,6 @@ void FieldGenerator::GenerateClassNameOrMapData(io::Printer *printer) const { GenerateObjcClassRef(printer, descriptor_); } -void FieldGenerator::GenerateStaticRefs(io::Printer *printer) const { - JavaType type = GetJavaType(descriptor_); - std::string staticref; - if (type == JAVATYPE_MESSAGE) { - staticref = "&" + - GetParameterType(descriptor_) + "_descriptor_"; - } else if (type == JAVATYPE_ENUM) { - staticref = "&" + - GetParameterType(descriptor_) + "_descriptor_"; - } else { - staticref = "NULL"; - } - printer->Print(" .descriptorRef = $staticref$,\n", "staticref", staticref); -} - SingleFieldGenerator::SingleFieldGenerator( const FieldDescriptor *descriptor, uint32_t *numHasBits) : FieldGenerator(descriptor) { @@ -333,7 +313,7 @@ void SingleFieldGenerator::GenerateFieldBuilderHeader(io::Printer* printer) "- (nonnull $classname$_Builder *)clear$capitalized_name$;\n"); if (IsGenerateProperties(descriptor_->file())) { - printer->Print(GetStorageType(descriptor_) == GetNonNullType(descriptor_) + printer->Print(GetStorageType(descriptor_) == GetNonNullType(descriptor_) ? "@property (" : "@property (nonnull, retain, "); printer->Print( variables_, @@ -600,10 +580,6 @@ void MapEntryFieldGenerator::GenerateFieldDataOffset(io::Printer *printer) printer->Print(variables_, " .offset = 0,\n"); } -void MapFieldGenerator::GenerateStaticRefs(io::Printer *printer) const { - printer->Print(variables_, " .descriptorRef = NULL,\n"); -} - void MapEntryFieldGenerator::GenerateFieldBuilderHeader(io::Printer* printer) const { } @@ -615,10 +591,6 @@ void MapEntryFieldGenerator::GenerateMessageOrBuilderProtocol( void MapEntryFieldGenerator::GenerateDeclaration(io::Printer* printer) const { } -void MapEntryFieldGenerator::GenerateStaticRefs(io::Printer *printer) const { - printer->Print(variables_, " .descriptorRef = NULL,\n"); -} - FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) : descriptor_(descriptor), field_generators_( diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.h b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.h index 1d7102b6b6..3691bc92bb 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.h +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_field.h @@ -83,7 +83,6 @@ class FieldGenerator { virtual void GenerateFieldDataOffset(io::Printer *printer) const; virtual void GenerateClassNameOrMapData(io::Printer *printer) const; - virtual void GenerateStaticRefs(io::Printer *printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); @@ -158,7 +157,6 @@ class MapFieldGenerator : public FieldGenerator { protected: virtual void GenerateClassNameOrMapData(io::Printer *printer) const; - virtual void GenerateStaticRefs(io::Printer *printer) const; private: const FieldDescriptor* key_field_; @@ -181,7 +179,6 @@ class MapEntryFieldGenerator : public FieldGenerator { protected: virtual void GenerateFieldDataOffset(io::Printer *printer) const; - virtual void GenerateStaticRefs(io::Printer *printer) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryFieldGenerator); diff --git a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc index b3ee9a4d65..974644a569 100644 --- a/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc +++ b/protobuf/compiler/src/google/protobuf/compiler/j2objc/j2objc_message.cc @@ -304,10 +304,7 @@ void MessageGenerator::GenerateHeader(io::Printer* printer) { "\n" "J2OBJC_STATIC_INIT($classname$)\n" "\n" - "J2OBJC_TYPE_LITERAL_HEADER($classname$)\n" - "\n" - "FOUNDATION_EXPORT ComGoogleProtobufDescriptors_Descriptor " - "* _Nonnull $classname$_descriptor_;\n", + "J2OBJC_TYPE_LITERAL_HEADER($classname$)\n", "classname", ClassName(descriptor_)); for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { @@ -358,7 +355,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "\n" "J2OBJC_INITIALIZED_DEFN($classname$);\n" "\n" - "ComGoogleProtobufDescriptors_Descriptor * _Nonnull " + "static ComGoogleProtobufDescriptors_Descriptor * _Nonnull " "$classname$_descriptor_;\n", "classname", ClassName(descriptor_)); @@ -459,7 +456,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "classname", ClassName(descriptor_), "flags", GetMessageFlags(descriptor_)); if (field_generators_.numMapFields() > 0) { - printer->Print("static CGPFieldData mapEntryFields[] = {\n"); + printer->Print("static const CGPFieldData mapEntryFields[] = {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) @@ -468,7 +465,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Print("};\n"); } - printer->Print("static CGPFieldData fields[] = {\n"); + printer->Print("static const CGPFieldData fields[] = {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)).GenerateFieldData(printer); @@ -493,7 +490,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { descriptor_->real_oneof_decl_count() > 0 ? "oneofs" : "NULL"); if (descriptor_->extension_count() > 0) { - printer->Print("static CGPFieldData extensionFields[] = {\n"); + printer->Print("static const CGPFieldData extensionFields[] = {\n"); printer->Indent(); for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator(descriptor_->extension(i)).GenerateFieldData(printer); diff --git a/protobuf/runtime/src/com/google/protobuf/Descriptors.h b/protobuf/runtime/src/com/google/protobuf/Descriptors.h index 1a7c6d2514..5f4bfc9fe5 100644 --- a/protobuf/runtime/src/com/google/protobuf/Descriptors.h +++ b/protobuf/runtime/src/com/google/protobuf/Descriptors.h @@ -116,7 +116,7 @@ J2OBJC_EMPTY_STATIC_INIT(ComGoogleProtobufDescriptors_EnumDescriptor) J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_EnumDescriptor) -@interface ComGoogleProtobufDescriptors_EnumValueDescriptor : NSObject +@interface ComGoogleProtobufDescriptors_UnknownEnumValueDescriptor : NSObject - (jint)getNumber; @@ -124,6 +124,10 @@ J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_EnumDescriptor) @end +@interface ComGoogleProtobufDescriptors_EnumValueDescriptor + : ComGoogleProtobufDescriptors_UnknownEnumValueDescriptor +@end + J2OBJC_EMPTY_STATIC_INIT(ComGoogleProtobufDescriptors_EnumValueDescriptor) J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_EnumValueDescriptor) @@ -142,4 +146,4 @@ J2OBJC_EMPTY_STATIC_INIT(ComGoogleProtobufDescriptors_OneofDescriptor) J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_OneofDescriptor) -#endif // __ComGoogleProtobufDescriptors_H__ +#endif // __ComGoogleProtobufDescriptors_H__ diff --git a/protobuf/runtime/src/com/google/protobuf/Descriptors.m b/protobuf/runtime/src/com/google/protobuf/Descriptors.m index 5e34185e44..c4464cdaf1 100644 --- a/protobuf/runtime/src/com/google/protobuf/Descriptors.m +++ b/protobuf/runtime/src/com/google/protobuf/Descriptors.m @@ -51,15 +51,6 @@ #import "java/util/Arrays.h" #import "java/util/Collections.h" -// Defines the field in the CGPValue union type to use for each field type. -#define VALUE_FIELD_Int valueInt -#define VALUE_FIELD_Long valueLong -#define VALUE_FIELD_Float valueFloat -#define VALUE_FIELD_Double valueDouble -#define VALUE_FIELD_Bool valueBool -#define VALUE_FIELD_Enum valueId -#define VALUE_FIELD_Retainable valueId - BOOL CGPIsRetainedType(CGPFieldJavaType type) { switch (type) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: @@ -67,8 +58,8 @@ BOOL CGPIsRetainedType(CGPFieldJavaType type) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: return NO; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: @@ -79,13 +70,13 @@ BOOL CGPIsRetainedType(CGPFieldJavaType type) { size_t CGPGetTypeSize(CGPFieldJavaType type) { #define GET_TYPE_SIZE_CASE(NAME) return sizeof(TYPE_##NAME); - SWITCH_TYPES_NO_ENUM(type, GET_TYPE_SIZE_CASE) + SWITCH_TYPES(type, GET_TYPE_SIZE_CASE) #undef GET_TYPE_SIZE_CASE } -IOSObjectArray *CreateFields(jint fieldCount, CGPFieldData *fieldData, - CGPDescriptor *containingType) { +static IOSObjectArray *CreateFields(jint fieldCount, const CGPFieldData *fieldData, + CGPDescriptor *containingType) { IOSObjectArray *fields = [IOSObjectArray newArrayWithLength:fieldCount type:ComGoogleProtobufDescriptors_FieldDescriptor_class_()]; @@ -104,7 +95,7 @@ size_t CGPGetTypeSize(CGPFieldJavaType type) { storageSize:storageSize]; } -void CGPInitFields(CGPDescriptor *descriptor, jint fieldCount, CGPFieldData *fieldData, +void CGPInitFields(CGPDescriptor *descriptor, jint fieldCount, const CGPFieldData *fieldData, jint oneofCount, const CGPOneofData *oneofData) { descriptor->fields_ = CreateFields(fieldCount, fieldData, descriptor); @@ -127,7 +118,7 @@ void CGPInitFields(CGPDescriptor *descriptor, jint fieldCount, CGPFieldData *fie } } -CGPDescriptor *NewMapEntryDescriptor(CGPFieldData *fieldData) { +static CGPDescriptor *NewMapEntryDescriptor(const CGPFieldData *fieldData) { CGPDescriptor *descriptor = [[CGPDescriptor alloc] init]; descriptor->fields_ = CreateFields(2, fieldData, descriptor); return descriptor; @@ -290,7 +281,7 @@ int SerializationOrderComp(const void *a, const void *b) { @implementation ComGoogleProtobufDescriptors_FieldDescriptor -static uint32_t TagFromData(CGPFieldData *data) { +static uint32_t TagFromData(const CGPFieldData *data) { BOOL isPacked = data->flags & CGPFieldFlagPacked; return CGPWireFormatMakeTag(data->number, CGPWireFormatForType(data->type, isPacked)); } @@ -313,8 +304,8 @@ static uint32_t TagFromData(CGPFieldData *data) { } // Default values for enums and message types can't be assigned in static data. -static void CGPFieldFixDefaultValue(CGPFieldDescriptor *descriptor) { - CGPFieldData *data = descriptor->data_; +static void CGPFieldUpdateValueType(CGPFieldDescriptor *descriptor) { + const CGPFieldData *data = descriptor->data_; switch (descriptor->javaType_) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: @@ -327,15 +318,12 @@ static void CGPFieldFixDefaultValue(CGPFieldDescriptor *descriptor) { Class enumClass = data->objcType; NSCAssert(enumClass != nil, @"Field data is missing objc enum type."); CGPEnumDescriptor *enumDescriptor = [enumClass performSelector:@selector(getDescriptor)]; - CGPEnumValueDescriptor *valueDescriptor = - IOSObjectArray_Get(enumDescriptor->values_, data->defaultValue.valueInt); - data->defaultValue.valueId = valueDescriptor->enum_; descriptor->valueType_ = enumDescriptor; break; } case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: if (data->defaultValue.valueId == nil) { - data->defaultValue.valueId = ComGoogleProtobufByteString_get_EMPTY(); + descriptor->valueType_ = ComGoogleProtobufByteString_get_EMPTY(); } else { // Default byte string data is written to static data as a length // prefixed c-string. @@ -346,7 +334,7 @@ static void CGPFieldFixDefaultValue(CGPFieldDescriptor *descriptor) { rawBytes += sizeof(length); CGPByteString *byteString = CGPNewByteString(length); memcpy(byteString->buffer_, rawBytes, length); - data->defaultValue.valueId = byteString; + descriptor->valueType_ = byteString; } break; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: { @@ -354,27 +342,21 @@ static void CGPFieldFixDefaultValue(CGPFieldDescriptor *descriptor) { descriptor->valueType_ = NewMapEntryDescriptor(data->mapEntryFields); break; } - CGPDescriptor *msgDescriptor = - data->descriptorRef ? (__bridge id) * (data->descriptorRef) : nil; - if (msgDescriptor == nil) { - // The descriptorRef wasn't specified, so use its accessor. - Class msgClass = data->objcType; - msgDescriptor = [msgClass performSelector:@selector(getDescriptor)]; - } + Class msgClass = data->objcType; + CGPDescriptor *msgDescriptor = [msgClass performSelector:@selector(getDescriptor)]; NSCAssert(msgDescriptor != nil, @"Field data is missing descriptor reference."); - data->defaultValue.valueId = msgDescriptor->defaultInstance_; descriptor->valueType_ = msgDescriptor; break; } } } -- (instancetype)initWithData:(CGPFieldData *)data { +- (instancetype)initWithData:(const CGPFieldData *)data { if (self = [self init]) { data_ = data; tag_ = TagFromData(data); javaType_ = [GetTypeObj(data->type)->javaType_ ordinal]; - CGPFieldFixDefaultValue(self); + CGPFieldUpdateValueType(self); } return self; } @@ -433,7 +415,7 @@ - (CGPEnumDescriptor *)getEnumType { } - (id)getDefaultValue { - return CGPFieldGetDefaultValue(self); + return CGPFieldGetDefaultValueObject(self); } - (ComGoogleProtobufDescriptorProtos_FieldOptions *)getOptions { @@ -453,17 +435,59 @@ - (ComGoogleProtobufDescriptorProtos_FieldOptions *)getOptions { J2OBJC_CLASS_TYPE_LITERAL_SOURCE(ComGoogleProtobufDescriptors_FieldDescriptor) -id CGPFieldGetDefaultValue(CGPFieldDescriptor *field) { +CGPValue CGPFieldGetDefaultValue(const CGPFieldDescriptor *field) { + CGPValue value; + switch (CGPFieldGetJavaType(field)) { + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: + value = field->data_->defaultValue; + break; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: + value.valueId = field->valueType_; + break; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: { + jint enumOrdinal = field->data_->defaultValue.valueInt; + CGPEnumDescriptor *enumDescriptor = (CGPEnumDescriptor *)field->valueType_; + CGPEnumValueDescriptor **valuesBuf = enumDescriptor->values_->buffer_; + value.valueEnum = valuesBuf[enumOrdinal]; + break; + } + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: + value.valueId = ((CGPDescriptor *)field->valueType_)->defaultInstance_; + break; + } + return value; +} + +id CGPFieldGetDefaultValueObject(CGPFieldDescriptor *field) { if (CGPFieldIsRepeated(field)) { return [JavaUtilCollections emptyList]; } - -#define GET_DEFAULT_VALUE_CASE(NAME) \ - return CGPToReflectionType##NAME(field->data_->defaultValue.VALUE_FIELD_##NAME, field); - - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(field), GET_DEFAULT_VALUE_CASE) - -#undef GET_DEFAULT_VALUE_CASE + switch (CGPFieldGetJavaType(field)) { + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: + return [JavaLangInteger valueOfWithInt:field->data_->defaultValue.valueInt]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: + return [JavaLangLong valueOfWithLong:field->data_->defaultValue.valueLong]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: + return [JavaLangFloat valueOfWithFloat:field->data_->defaultValue.valueFloat]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: + return [JavaLangDouble valueOfWithDouble:field->data_->defaultValue.valueDouble]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: + return [JavaLangBoolean valueOfWithBoolean:field->data_->defaultValue.valueBool]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: + return field->data_->defaultValue.valueId; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: + return field->valueType_; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: + return ((CGPEnumDescriptor *)field->valueType_) + ->values_->buffer_[field->data_->defaultValue.valueInt]; + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: + return ((CGPDescriptor *)field->valueType_)->defaultInstance_; + } } CGPEnumValueDescriptor *CGPEnumValueDescriptorFromInt(CGPEnumDescriptor *enumType, jint value) { @@ -476,8 +500,23 @@ id CGPFieldGetDefaultValue(CGPFieldDescriptor *field) { return valueDescriptor; } } - // If proto3 (not closed), the UNRECOGNIZED value is the last values element. - return enumType->is_closed_ ? nil : valuesBuf[count - 1]; + + if (enumType->is_closed_) { + return nil; + } + + CGPEnumValueDescriptor *unrecognizedValue = valuesBuf[count - 1]; + if (value == -1) { + // -1 is the value generated for the UNRECOGNIZED constant in open enums. + // If the value is -1, we return the UNRECOGNIZED descriptor. + return unrecognizedValue; + } else { + CGPEnumValueDescriptor *unknownValue = (CGPEnumValueDescriptor *)AUTORELEASE( + [[ComGoogleProtobufDescriptors_UnknownEnumValueDescriptor alloc] init]); + unknownValue->number_ = value; + unknownValue->enum_ = unrecognizedValue->enum_; + return unknownValue; + } } @implementation ComGoogleProtobufDescriptors_EnumDescriptor @@ -503,7 +542,7 @@ - (CGPEnumValueDescriptor *)findValueByNumberWithInt:(jint)number { J2OBJC_CLASS_TYPE_LITERAL_SOURCE(ComGoogleProtobufDescriptors_EnumDescriptor) -@implementation ComGoogleProtobufDescriptors_EnumValueDescriptor +@implementation ComGoogleProtobufDescriptors_UnknownEnumValueDescriptor - (jint)getNumber { return number_; @@ -513,6 +552,10 @@ - (NSString *)getName { return [enum_ name]; } +@end + +@implementation ComGoogleProtobufDescriptors_EnumValueDescriptor + J2OBJC_ETERNAL_SINGLETON @end diff --git a/protobuf/runtime/src/com/google/protobuf/Descriptors_PackagePrivate.h b/protobuf/runtime/src/com/google/protobuf/Descriptors_PackagePrivate.h index 5829afda29..d7d8628d70 100644 --- a/protobuf/runtime/src/com/google/protobuf/Descriptors_PackagePrivate.h +++ b/protobuf/runtime/src/com/google/protobuf/Descriptors_PackagePrivate.h @@ -45,6 +45,7 @@ typedef union { jdouble valueDouble; bool valueBool; __unsafe_unretained id valueId; + __unsafe_unretained ComGoogleProtobufDescriptors_EnumValueDescriptor *valueEnum; const void *valuePtr; } CGPValue; @@ -53,8 +54,7 @@ typedef union { #define CGPValueField_Float valueFloat #define CGPValueField_Double valueDouble #define CGPValueField_Bool valueBool -#define CGPValueField_Enum valueId -#define CGPValueField_Retainable valueId +#define CGPValueField_Enum valueEnum #define CGPValueField_Id valueId typedef NS_OPTIONS(uint32_t, CGPMessageFlags) { @@ -80,9 +80,8 @@ typedef struct CGPFieldData { uint32_t offset; union { Class objcType; - struct CGPFieldData *mapEntryFields; + const struct CGPFieldData *mapEntryFields; }; - const __unsafe_unretained id *descriptorRef; const char *containingType; const char *optionsData; } CGPFieldData; @@ -116,16 +115,17 @@ typedef struct CGPOneofData { @interface ComGoogleProtobufDescriptors_FieldDescriptor () { @package - CGPFieldData *data_; + const CGPFieldData *data_; uint32_t tag_; CGPFieldJavaType javaType_; - // Either nil, a Descriptor or a EnumDescriptor depending on the field type. + // Either nil, a ComGoogleProtobufByteString, a Descriptor or a EnumDescriptor depending on the + // field type. id valueType_; ComGoogleProtobufDescriptorProtos_FieldOptions *fieldOptions_; CGPOneofDescriptor *containingOneof_; } -- (instancetype)initWithData:(CGPFieldData *)data; +- (instancetype)initWithData:(const CGPFieldData *)data; @end @@ -142,7 +142,7 @@ typedef struct CGPOneofData { @end -@interface ComGoogleProtobufDescriptors_EnumValueDescriptor () { +@interface ComGoogleProtobufDescriptors_UnknownEnumValueDescriptor () { @package JavaLangEnum *enum_; jint number_; @@ -160,26 +160,13 @@ typedef struct CGPOneofData { @end -// Functions that convert a value from its field storage type to the type -// expected by a reflection accessor. (accessing with a descriptor) -// For enums, the reflection type is a EnumValueDescriptor. -#define CGPToReflectionTypeInt(value, field) [JavaLangInteger valueOfWithInt:value] -#define CGPToReflectionTypeLong(value, field) [JavaLangLong valueOfWithLong:value] -#define CGPToReflectionTypeFloat(value, field) [JavaLangFloat valueOfWithFloat:value] -#define CGPToReflectionTypeDouble(value, field) [JavaLangDouble valueOfWithDouble:value] -#define CGPToReflectionTypeBool(value, field) [JavaLangBoolean valueOfWithBoolean:value] -#define CGPToReflectionTypeEnum(value, field) \ - ((CGPEnumDescriptor *)field->valueType_)->values_->buffer_[[(JavaLangEnum *)value ordinal]] -#define CGPToReflectionTypeRetainable(value, field) RETAIN_AND_AUTORELEASE(value) - CF_EXTERN_C_BEGIN NS_RETURNS_RETAINED CGPDescriptor *CGPInitDescriptor(Class messageClass, Class builderClass, CGPMessageFlags flags, size_t storageSize); -void CGPInitFields( - CGPDescriptor *descriptor, jint fieldCount, CGPFieldData *fieldData, - jint oneofCount, const CGPOneofData *oneofData); +void CGPInitFields(CGPDescriptor *descriptor, jint fieldCount, const CGPFieldData *fieldData, + jint oneofCount, const CGPOneofData *oneofData); CGP_ALWAYS_INLINE BOOL CGPIsExtendable(const CGPDescriptor *descriptor) { return descriptor->flags_ & CGPMessageFlagExtendable; @@ -264,11 +251,12 @@ CGP_ALWAYS_INLINE BOOL CGPJavaTypeIsEnum(CGPFieldJavaType type) { return type == ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM; } -CGP_ALWAYS_INLINE jint CGPEnumGetIntValue(CGPEnumDescriptor *descriptor, id enumObj) { - return *(jint *)((char *)(ARCBRIDGE void *)enumObj + descriptor->valueOffset_); +CGP_ALWAYS_INLINE jint CGPEnumGetIntValue(CGPEnumDescriptor *descriptor, TYPE_Enum enumObj) { + return enumObj->number_; } -id CGPFieldGetDefaultValue(CGPFieldDescriptor *field); +id CGPFieldGetDefaultValueObject(CGPFieldDescriptor *field); +CGPValue CGPFieldGetDefaultValue(const CGPFieldDescriptor *field); Class CGPOneofGetCaseClass(CGPOneofDescriptor *oneof); @@ -306,4 +294,107 @@ J2OBJC_FIELD_SETTER(ComGoogleProtobufDescriptors_FieldDescriptor_Type, javaType_ J2OBJC_FIELD_SETTER(ComGoogleProtobufDescriptors_FieldDescriptor_JavaType, defaultDefault_, id) +// Functions that box a value from its field storage type into an object type. +// For enums, the boxed type is a Java enum object. +CGP_ALWAYS_INLINE JavaLangInteger *CGPBoxedValueInt(jint value) { + return [JavaLangInteger valueOfWithInt:value]; +} +CGP_ALWAYS_INLINE JavaLangLong *CGPBoxedValueLong(jlong value) { + return [JavaLangLong valueOfWithLong:value]; +} +CGP_ALWAYS_INLINE JavaLangFloat *CGPBoxedValueFloat(jfloat value) { + return [JavaLangFloat valueOfWithFloat:value]; +} +CGP_ALWAYS_INLINE JavaLangDouble *CGPBoxedValueDouble(jdouble value) { + return [JavaLangDouble valueOfWithDouble:value]; +} +CGP_ALWAYS_INLINE JavaLangBoolean *CGPBoxedValueBool(bool value) { + return [JavaLangBoolean valueOfWithBoolean:value]; +} +CGP_ALWAYS_INLINE JavaLangEnum *CGPBoxedValueEnum( + CGPEnumValueDescriptor *value) { + return value->enum_; +} +CGP_ALWAYS_INLINE id CGPBoxedValueId(id value) { return value; } + +// Functions that unbox a value into its primitive type. +CGP_ALWAYS_INLINE jint CGPUnboxValueInt(JavaLangInteger *value) { return [value intValue]; } +CGP_ALWAYS_INLINE jlong CGPUnboxValueLong(JavaLangLong *value) { return [value longLongValue]; } +CGP_ALWAYS_INLINE jfloat CGPUnboxValueFloat(JavaLangFloat *value) { return [value floatValue]; } +CGP_ALWAYS_INLINE jdouble CGPUnboxValueDouble(JavaLangDouble *value) { return [value doubleValue]; } +CGP_ALWAYS_INLINE bool CGPUnboxValueBool(JavaLangBoolean *value) { return [value booleanValue]; } +CGP_ALWAYS_INLINE CGPEnumValueDescriptor *CGPUnboxValueEnum( + JavaLangEnum *value) { + return [value getValueDescriptor]; +} +CGP_ALWAYS_INLINE id CGPUnboxValueId(id value) { return value; } + +// Functions that convert a value from its reflection to its storage type. +CGP_ALWAYS_INLINE jint CGPFromReflectionTypeInt(JavaLangInteger *value) { return [value intValue]; } +CGP_ALWAYS_INLINE jlong CGPFromReflectionTypeLong(JavaLangLong *value) { + return [value longLongValue]; +} +CGP_ALWAYS_INLINE jfloat CGPFromReflectionTypeFloat(JavaLangFloat *value) { + return [value floatValue]; +} +CGP_ALWAYS_INLINE jdouble CGPFromReflectionTypeDouble(JavaLangDouble *value) { + return [value doubleValue]; +} +CGP_ALWAYS_INLINE bool CGPFromReflectionTypeBool(JavaLangBoolean *value) { + return [value booleanValue]; +} +CGP_ALWAYS_INLINE CGPEnumValueDescriptor *CGPFromReflectionTypeEnum(CGPEnumValueDescriptor *value) { + return value; +} +CGP_ALWAYS_INLINE id CGPFromReflectionTypeId(id value) { return value; } + +// Functions that convert a value from its field storage type to the type +// expected by a reflection accessor. (accessing with a descriptor) +// For enums, the reflection type is a EnumValueDescriptor. +CGP_ALWAYS_INLINE JavaLangInteger *CGPToReflectionTypeInt(jint value) { + return [JavaLangInteger valueOfWithInt:value]; +} +CGP_ALWAYS_INLINE JavaLangLong *CGPToReflectionTypeLong(jlong value) { + return [JavaLangLong valueOfWithLong:value]; +} +CGP_ALWAYS_INLINE JavaLangFloat *CGPToReflectionTypeFloat(jfloat value) { + return [JavaLangFloat valueOfWithFloat:value]; +} +CGP_ALWAYS_INLINE JavaLangDouble *CGPToReflectionTypeDouble(jdouble value) { + return [JavaLangDouble valueOfWithDouble:value]; +} +CGP_ALWAYS_INLINE JavaLangBoolean *CGPToReflectionTypeBool(bool value) { + return [JavaLangBoolean valueOfWithBoolean:value]; +} +CGP_ALWAYS_INLINE CGPEnumValueDescriptor *CGPToReflectionTypeEnum(CGPEnumValueDescriptor *value) { + return RETAIN_AND_AUTORELEASE(value); +} +CGP_ALWAYS_INLINE id CGPToReflectionTypeId(id value) { return RETAIN_AND_AUTORELEASE(value); } + +// Functions that convert a value from its field storage type to its external +// type. +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Int ToExternalTypeInt(TYPE_Int value) { return value; } +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Long ToExternalTypeLong(TYPE_Long value) { return value; } +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Float ToExternalTypeFloat(TYPE_Float value) { return value; } +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Double ToExternalTypeDouble(TYPE_Double value) { return value; } +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Bool ToExternalTypeBool(TYPE_Bool value) { return value; } +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Enum ToExternalTypeEnum(TYPE_Enum value) { + return RETAIN_AND_AUTORELEASE(value->enum_); +} +CGP_ALWAYS_INLINE EXTERNAL_TYPE_Id ToExternalTypeId(TYPE_Id value) { + return RETAIN_AND_AUTORELEASE(value); +} + +// Functions that convert a value from its external type to its field storage +// type. +CGP_ALWAYS_INLINE TYPE_Int ToTypeInt(EXTERNAL_TYPE_Int value) { return value; } +CGP_ALWAYS_INLINE TYPE_Long ToTypeLong(EXTERNAL_TYPE_Long value) { return value; } +CGP_ALWAYS_INLINE TYPE_Float ToTypeFloat(EXTERNAL_TYPE_Float value) { return value; } +CGP_ALWAYS_INLINE TYPE_Double ToTypeDouble(EXTERNAL_TYPE_Double value) { return value; } +CGP_ALWAYS_INLINE TYPE_Bool ToTypeBool(EXTERNAL_TYPE_Bool value) { return value; } +CGP_ALWAYS_INLINE TYPE_Enum ToTypeEnum(EXTERNAL_TYPE_Enum value) { + return [value getValueDescriptor]; +} +CGP_ALWAYS_INLINE TYPE_Id ToTypeId(EXTERNAL_TYPE_Id value) { return value; } + #endif // __ComGoogleProtobufDescriptors_PackagePrivate_H__ diff --git a/protobuf/runtime/src/com/google/protobuf/ExtensionLite.h b/protobuf/runtime/src/com/google/protobuf/ExtensionLite.h index 000eca72db..7fddbc60ee 100644 --- a/protobuf/runtime/src/com/google/protobuf/ExtensionLite.h +++ b/protobuf/runtime/src/com/google/protobuf/ExtensionLite.h @@ -46,7 +46,7 @@ struct CGPFieldData; CGPFieldDescriptor *fieldDescriptor_; } -- (instancetype)initWithFieldData:(struct CGPFieldData *)data; +- (instancetype)initWithFieldData:(const struct CGPFieldData *)data; - (ComGoogleProtobufDescriptors_FieldDescriptor *)getDescriptor; @@ -60,7 +60,7 @@ typedef ComGoogleProtobufExtensionLite CGPExtensionLite; CF_EXTERN_C_BEGIN void ComGoogleProtobufExtensionLite_initWithFieldData_(CGPExtensionLite *self, - struct CGPFieldData *data); + const struct CGPFieldData *data); CF_EXTERN_C_END J2OBJC_EMPTY_STATIC_INIT(ComGoogleProtobufExtensionLite) diff --git a/protobuf/runtime/src/com/google/protobuf/ExtensionLite.m b/protobuf/runtime/src/com/google/protobuf/ExtensionLite.m index a2df6097f3..9bcfad1fef 100644 --- a/protobuf/runtime/src/com/google/protobuf/ExtensionLite.m +++ b/protobuf/runtime/src/com/google/protobuf/ExtensionLite.m @@ -36,7 +36,7 @@ @implementation ComGoogleProtobufExtensionLite -- (instancetype)initWithFieldData:(struct CGPFieldData *)data { +- (instancetype)initWithFieldData:(const struct CGPFieldData *)data { ComGoogleProtobufExtensionLite_initWithFieldData_(self, data); return self; } @@ -61,7 +61,7 @@ - (jint)getNumber { @end void ComGoogleProtobufExtensionLite_initWithFieldData_(CGPExtensionLite *self, - struct CGPFieldData *data) { + const struct CGPFieldData *data) { NSObject_init(self); self->fieldDescriptor_ = [[CGPFieldDescriptor alloc] initWithData:data]; } diff --git a/protobuf/runtime/src/com/google/protobuf/ExtensionRegistry.mm b/protobuf/runtime/src/com/google/protobuf/ExtensionRegistry.mm index c0f9a18f99..33e3a20338 100644 --- a/protobuf/runtime/src/com/google/protobuf/ExtensionRegistry.mm +++ b/protobuf/runtime/src/com/google/protobuf/ExtensionRegistry.mm @@ -122,7 +122,7 @@ - (instancetype)initWithField:(CGPFieldDescriptor *)field { descriptor_ = field; if (CGPFieldTypeIsMessage(field)) { // No need to retain. Default message values are eternal. - defaultInstance_ = CGPFieldGetDefaultValue(field); + defaultInstance_ = CGPFieldGetDefaultValueObject(field); } } return self; diff --git a/protobuf/runtime/src/com/google/protobuf/FieldTypes.h b/protobuf/runtime/src/com/google/protobuf/FieldTypes.h index 5c61026278..d0b4c81390 100644 --- a/protobuf/runtime/src/com/google/protobuf/FieldTypes.h +++ b/protobuf/runtime/src/com/google/protobuf/FieldTypes.h @@ -36,6 +36,7 @@ #define __ComGoogleProtobufFieldTypes_H__ #import "com/google/protobuf/ProtocolMessageEnum.h" +#import "com/google/protobuf/common.h" #import "java/lang/Boolean.h" #import "java/lang/Double.h" #import "java/lang/Enum.h" @@ -43,154 +44,100 @@ #import "java/lang/Integer.h" #import "java/lang/Long.h" +@class ComGoogleProtobufDescriptors_EnumValueDescriptor; @class ComGoogleProtobufDescriptors_FieldDescriptor_JavaType; @class ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type; -#define TYPE_Int jint -#define TYPE_Long jlong -#define TYPE_Float jfloat -#define TYPE_Double jdouble -#define TYPE_Bool bool -#define TYPE_Enum id -#define TYPE_Id id -#define TYPE_Retainable id - -#define TYPE_RETAIN_Int(value) value -#define TYPE_RETAIN_Long(value) value -#define TYPE_RETAIN_Float(value) value -#define TYPE_RETAIN_Double(value) value -#define TYPE_RETAIN_Bool(value) value -#define TYPE_RETAIN_Enum(value) value -#if __has_feature(objc_arc) -#define TYPE_RETAIN_Retainable(value) value -#else -#define TYPE_RETAIN_Retainable(value) [value retain] -#endif - -#define TYPE_ASSIGN_Int(assignee, value) assignee = value -#define TYPE_ASSIGN_Long(assignee, value) assignee = value -#define TYPE_ASSIGN_Float(assignee, value) assignee = value -#define TYPE_ASSIGN_Double(assignee, value) assignee = value -#define TYPE_ASSIGN_Bool(assignee, value) assignee = value -#define TYPE_ASSIGN_Enum(assignee, value) assignee = value -#if __has_feature(objc_arc) -#define TYPE_ASSIGN_Retainable(assignee, value) assignee = value -#else -#define TYPE_ASSIGN_Retainable(assignee, value) \ - ([assignee autorelease], assignee = [value retain]) -#endif - -#define HASH_Int(value) value -#define HASH_Long(value) (int)((uint64_t)value ^ ((uint64_t)value >> 32)) -#define HASH_Float(value) *(int *)&value -#define HASH_Double(value) (int)(*(uint64_t *)&value ^ (*(uint64_t *)&value >> 32)) -#define HASH_Bool(value) (value ? 1231 : 1237) -#define HASH_Id(value) (int)[value hash] - -// Functions that box a value from its field storage type into an object type. -// For enums, the boxed type is the same as its storage type. (a Java enum -// object) -#define CGPBoxedValueInt(value) [JavaLangInteger valueOfWithInt:value] -#define CGPBoxedValueLong(value) [JavaLangLong valueOfWithLong:value] -#define CGPBoxedValueFloat(value) [JavaLangFloat valueOfWithFloat:value] -#define CGPBoxedValueDouble(value) [JavaLangDouble valueOfWithDouble:value] -#define CGPBoxedValueBool(value) [JavaLangBoolean valueOfWithBoolean:value] -#define CGPBoxedValueId(value) value - -// Functions that unbox a value into its primitive type. -#define CGPUnboxValueInt(value) [value intValue] -#define CGPUnboxValueLong(value) [value longLongValue] -#define CGPUnboxValueFloat(value) [value floatValue] -#define CGPUnboxValueDouble(value) [value doubleValue] -#define CGPUnboxValueBool(value) [value booleanValue] -#define CGPUnboxValueEnum(value) value -#define CGPUnboxValueRetainable(value) value - -// Functions that convert a value from its reflection to its storage type. -#define CGPFromReflectionTypeInt(value) [value intValue] -#define CGPFromReflectionTypeLong(value) [value longLongValue] -#define CGPFromReflectionTypeFloat(value) [value floatValue] -#define CGPFromReflectionTypeDouble(value) [value doubleValue] -#define CGPFromReflectionTypeBool(value) [value booleanValue] -#define CGPFromReflectionTypeEnum(value) ((CGPEnumValueDescriptor *)value)->enum_ -#define CGPFromReflectionTypeRetainable(value) value +typedef jint TYPE_Int; +typedef jlong TYPE_Long; +typedef jfloat TYPE_Float; +typedef jdouble TYPE_Double; +typedef bool TYPE_Bool; +typedef ComGoogleProtobufDescriptors_EnumValueDescriptor *TYPE_Enum; +typedef id TYPE_Id; + +typedef TYPE_Int EXTERNAL_TYPE_Int; +typedef TYPE_Long EXTERNAL_TYPE_Long; +typedef TYPE_Float EXTERNAL_TYPE_Float; +typedef TYPE_Double EXTERNAL_TYPE_Double; +typedef TYPE_Bool EXTERNAL_TYPE_Bool; +typedef JavaLangEnum *EXTERNAL_TYPE_Enum; +typedef TYPE_Id EXTERNAL_TYPE_Id; + +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Int(jint *assignee, jint value) { *assignee = value; } +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Long(jlong *assignee, jlong value) { *assignee = value; } +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Float(jfloat *assignee, jfloat value) { *assignee = value; } +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Double(jdouble *assignee, jdouble value) { *assignee = value; } +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Bool(bool *assignee, bool value) { *assignee = value; } +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Enum(id *assignee, id value) { + __unused id unused = AUTORELEASE(*assignee); + *assignee = RETAIN_(value); +} +CGP_ALWAYS_INLINE void TYPE_ASSIGN_Id(id *assignee, id value) { + __unused id unused = AUTORELEASE(*assignee); + *assignee = RETAIN_(value); +} + +CGP_ALWAYS_INLINE int HASH_Int(jint value) { return value; } +CGP_ALWAYS_INLINE int HASH_Long(jlong value) { + return (int)((uint64_t)value ^ ((uint64_t)value >> 32)); +} +CGP_ALWAYS_INLINE int HASH_Float(jfloat value) { + uint32_t bits; + memcpy(&bits, &value, sizeof(bits)); + return bits; +} +CGP_ALWAYS_INLINE int HASH_Double(jdouble value) { + uint64_t bits; + memcpy(&bits, &value, sizeof(bits)); + return (int)(bits ^ (bits >> 32)); +} +CGP_ALWAYS_INLINE int HASH_Bool(bool value) { return (value ? 1231 : 1237); } +CGP_ALWAYS_INLINE int HASH_Enum(id value) { return (int)[value hash]; } +CGP_ALWAYS_INLINE int HASH_Id(id value) { return (int)[value hash]; } // Creates a switch statement over the java types grouping enums together with // the other object types. -#define SWITCH_TYPES_NO_ENUM(type, CASE_MACRO) \ - switch (type) { \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: \ - CASE_MACRO(Int) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: \ - CASE_MACRO(Long) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: \ - CASE_MACRO(Float) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: \ - CASE_MACRO(Double) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: \ - CASE_MACRO(Bool) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: \ +#define SWITCH_TYPES(type, TYPE_MACRO) \ + switch (type) { \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: \ + TYPE_MACRO(Int) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: \ + TYPE_MACRO(Long) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: \ + TYPE_MACRO(Float) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: \ + TYPE_MACRO(Double) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: \ + TYPE_MACRO(Bool) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: \ + TYPE_MACRO(Enum) \ + break; \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: \ case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: \ - CASE_MACRO(Id) \ + case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: \ + TYPE_MACRO(Id) \ + break; \ } -// Creates a switch statement over the java types separating enums from the -// other object types. -#define SWITCH_TYPES_WITH_ENUM(type, CASE_MACRO) \ - switch (type) { \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_INT: \ - CASE_MACRO(Int) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_LONG: \ - CASE_MACRO(Long) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: \ - CASE_MACRO(Float) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: \ - CASE_MACRO(Double) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: \ - CASE_MACRO(Bool) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: \ - CASE_MACRO(Retainable) \ - case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: \ - CASE_MACRO(Enum) \ - } - - -// Declares the given macro once for each java field type, grouping enums and -// the other object types together as "Id". Non-retainable types use the -// PRIMITIVE_TYPE_MACRO, retainable types use the RETAINABLE_TYPE_MACRO -#define FOR_EACH_TYPE_NO_ENUM(PRIMITIVE_TYPE_MACRO, RETAINABLE_TYPE_MACRO) \ - PRIMITIVE_TYPE_MACRO(Int) \ - PRIMITIVE_TYPE_MACRO(Long) \ - PRIMITIVE_TYPE_MACRO(Float) \ - PRIMITIVE_TYPE_MACRO(Double) \ - PRIMITIVE_TYPE_MACRO(Bool) \ - RETAINABLE_TYPE_MACRO(Id) - - -// Declares the given macro once for each java field type, declaring it -// separately for enums (as "Enum) and the other object types (as "Retainable"). -#define FOR_EACH_TYPE_WITH_ENUM(MACRO) \ - MACRO(Int) \ - MACRO(Long) \ - MACRO(Float) \ - MACRO(Double) \ - MACRO(Bool) \ - MACRO(Enum) \ - MACRO(Retainable) - // Declares the given macro once for each java field type except for retainable -//types. -#define FOR_EACH_TYPE_NO_RETAINABLE(MACRO) \ - MACRO(Int) \ - MACRO(Long) \ - MACRO(Float) \ - MACRO(Double) \ - MACRO(Bool) \ - MACRO(Enum) +// types. +#define FOR_EACH_PRIMITIVE_TYPE(PRIMITIVE_TYPE_MACRO) \ + PRIMITIVE_TYPE_MACRO(Int) \ + PRIMITIVE_TYPE_MACRO(Long) \ + PRIMITIVE_TYPE_MACRO(Float) \ + PRIMITIVE_TYPE_MACRO(Double) \ + PRIMITIVE_TYPE_MACRO(Bool) + +#define FOR_EACH_TYPE(TYPE_MACRO) \ + FOR_EACH_PRIMITIVE_TYPE(TYPE_MACRO) \ + TYPE_MACRO(Enum) \ + TYPE_MACRO(Id) // The remainder of this file is copied from the translation of the types // FieldDescriptor.Type and FieldDescriptor.JavaType in Descriptor.java. @@ -218,7 +165,7 @@ typedef NS_ENUM(NSUInteger, ComGoogleProtobufDescriptors_FieldDescriptor_Type_En typedef ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum CGPFieldType; -@interface ComGoogleProtobufDescriptors_FieldDescriptor_Type : JavaLangEnum < NSCopying > +@interface ComGoogleProtobufDescriptors_FieldDescriptor_Type : JavaLangEnum #pragma mark Public @@ -226,7 +173,9 @@ typedef ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum CGPFieldType; - (ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type *)toProto; -+ (ComGoogleProtobufDescriptors_FieldDescriptor_Type *)valueOfWithComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type:(ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type *)type; ++ (ComGoogleProtobufDescriptors_FieldDescriptor_Type *) + valueOfWithComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type: + (ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type *)type; #pragma mark Package-Private @@ -241,7 +190,8 @@ typedef ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum CGPFieldType; J2OBJC_STATIC_INIT(ComGoogleProtobufDescriptors_FieldDescriptor_Type) /*! INTERNAL ONLY - Use enum accessors declared below. */ -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type *ComGoogleProtobufDescriptors_FieldDescriptor_Type_values_[]; +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type + *ComGoogleProtobufDescriptors_FieldDescriptor_Type_values_[]; inline ComGoogleProtobufDescriptors_FieldDescriptor_Type * ComGoogleProtobufDescriptors_FieldDescriptor_Type_get_DOUBLE(void); @@ -315,13 +265,17 @@ inline ComGoogleProtobufDescriptors_FieldDescriptor_Type * ComGoogleProtobufDescriptors_FieldDescriptor_Type_get_SINT64(void); J2OBJC_ENUM_CONSTANT(ComGoogleProtobufDescriptors_FieldDescriptor_Type, SINT64) -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type *ComGoogleProtobufDescriptors_FieldDescriptor_Type_valueOfWithComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type_(ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type *type); +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type * +ComGoogleProtobufDescriptors_FieldDescriptor_Type_valueOfWithComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type_( + ComGoogleProtobufDescriptorProtos_FieldDescriptorProto_Type *type); FOUNDATION_EXPORT IOSObjectArray *ComGoogleProtobufDescriptors_FieldDescriptor_Type_values(void); -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type *ComGoogleProtobufDescriptors_FieldDescriptor_Type_valueOfWithNSString_(NSString *name); +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type * +ComGoogleProtobufDescriptors_FieldDescriptor_Type_valueOfWithNSString_(NSString *name); -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type *ComGoogleProtobufDescriptors_FieldDescriptor_Type_fromOrdinal(NSUInteger ordinal); +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_Type * +ComGoogleProtobufDescriptors_FieldDescriptor_Type_fromOrdinal(NSUInteger ordinal); J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_FieldDescriptor_Type) @@ -337,7 +291,7 @@ typedef NS_ENUM(NSUInteger, ComGoogleProtobufDescriptors_FieldDescriptor_JavaTyp ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE = 8, }; -@interface ComGoogleProtobufDescriptors_FieldDescriptor_JavaType : JavaLangEnum < NSCopying > +@interface ComGoogleProtobufDescriptors_FieldDescriptor_JavaType : JavaLangEnum #pragma mark Package-Private @@ -352,7 +306,8 @@ typedef NS_ENUM(NSUInteger, ComGoogleProtobufDescriptors_FieldDescriptor_JavaTyp J2OBJC_STATIC_INIT(ComGoogleProtobufDescriptors_FieldDescriptor_JavaType) /*! INTERNAL ONLY - Use enum accessors declared below. */ -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType *ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_values_[]; +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType + *ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_values_[]; inline ComGoogleProtobufDescriptors_FieldDescriptor_JavaType * ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_get_INT(void); @@ -393,10 +348,12 @@ J2OBJC_ENUM_CONSTANT(ComGoogleProtobufDescriptors_FieldDescriptor_JavaType, MESS FOUNDATION_EXPORT IOSObjectArray *ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_values( void); -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType *ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_valueOfWithNSString_(NSString *name); +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType * +ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_valueOfWithNSString_(NSString *name); -FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType *ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_fromOrdinal(NSUInteger ordinal); +FOUNDATION_EXPORT ComGoogleProtobufDescriptors_FieldDescriptor_JavaType * +ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_fromOrdinal(NSUInteger ordinal); J2OBJC_TYPE_LITERAL_HEADER(ComGoogleProtobufDescriptors_FieldDescriptor_JavaType) -#endif // __ComGoogleProtobufFieldTypes_H__ +#endif // __ComGoogleProtobufFieldTypes_H__ diff --git a/protobuf/runtime/src/com/google/protobuf/GeneratedMessage.mm b/protobuf/runtime/src/com/google/protobuf/GeneratedMessage.mm index 0027d399ff..6fe378209b 100644 --- a/protobuf/runtime/src/com/google/protobuf/GeneratedMessage.mm +++ b/protobuf/runtime/src/com/google/protobuf/GeneratedMessage.mm @@ -71,8 +71,8 @@ #define NIL_CHECK_Float(value) #define NIL_CHECK_Double(value) #define NIL_CHECK_Bool(value) -#define NIL_CHECK_Enum(value) (void)nil_chk(value); -#define NIL_CHECK_Retainable(value) (void)nil_chk(value); +#define NIL_CHECK_Enum(value) (void)nil_chk(value) +#define NIL_CHECK_Id(value) (void)nil_chk(value) // Forward declarations. class CGPExtensionValue; @@ -90,33 +90,17 @@ static inline int SerializedSizeForMessage(ComGoogleProtobufGeneratedMessage *ms static void MessageToString(id msg, CGPDescriptor *descriptor, NSMutableString *builder, int indent); -#define REPEATED_PRIMITIVE_FIELD_GETTER_IMP(NAME) \ - CGP_ALWAYS_INLINE TYPE_##NAME CGPRepeatedFieldGet##NAME(CGPRepeatedField *field, jint idx) { \ - CGPRepeatedFieldCheckBounds(field, idx); \ - return ((TYPE_##NAME *)field->data->buffer)[idx]; \ - } - -#define REPEATED_RETAINABLE_FIELD_GETTER_IMP(NAME) \ - CGP_ALWAYS_INLINE TYPE_##NAME CGPRepeatedFieldGet##NAME(CGPRepeatedField *field, jint idx) { \ - CGPRepeatedFieldCheckBounds(field, idx); \ - return RETAIN_AND_AUTORELEASE(((TYPE_##NAME *)field->data->buffer)[idx]); \ - } - -FOR_EACH_TYPE_NO_ENUM(REPEATED_PRIMITIVE_FIELD_GETTER_IMP, REPEATED_RETAINABLE_FIELD_GETTER_IMP) - -#undef REPEATED_PRIMITIVE_FIELD_GETTER_IMP -#undef REPEATED_RETAINABLE_FIELD_GETTER_IMP - #define REPEATED_FIELD_ADDER_IMP(NAME) \ CGP_ALWAYS_INLINE void CGPRepeatedFieldAdd##NAME(CGPRepeatedField *field, TYPE_##NAME value) { \ uint32_t total_size = CGPRepeatedFieldTotalSize(field); \ if (CGPRepeatedFieldSize(field) == total_size) { \ CGPRepeatedFieldReserve(field, total_size + 1, sizeof(TYPE_##NAME)); \ } \ - ((TYPE_##NAME *)field->data->buffer)[field->data->size++] = TYPE_RETAIN_##NAME(value); \ + TYPE_##NAME *ptr = &((TYPE_##NAME *)field->data->buffer)[field->data->size++]; \ + TYPE_ASSIGN_##NAME(ptr, value); \ } -FOR_EACH_TYPE_WITH_ENUM(REPEATED_FIELD_ADDER_IMP) +FOR_EACH_TYPE(REPEATED_FIELD_ADDER_IMP) #undef REPEATED_FIELD_ADDER_IMP @@ -125,10 +109,10 @@ static void MessageToString(id msg, CGPDescriptor *descriptor, NSMutableString * TYPE_##NAME value) { \ CGPRepeatedFieldCheckBounds(field, idx); \ TYPE_##NAME *ptr = &((TYPE_##NAME *)field->data->buffer)[idx]; \ - TYPE_ASSIGN_##NAME(*ptr, value); \ + TYPE_ASSIGN_##NAME(ptr, value); \ } -FOR_EACH_TYPE_WITH_ENUM(REPEATED_FIELD_SETTER_IMP) +FOR_EACH_TYPE(REPEATED_FIELD_SETTER_IMP) #undef REPEATED_FIELD_SETTER_IMP @@ -302,23 +286,37 @@ static inline BOOL ClearPreviousOneof(id msg, CGPHasLocator loc, uintptr_t ptr) return wasCleared; } -#define REPEATED_FIELD_PTR(msg, offset) ((CGPRepeatedField *)((uint8_t *)msg + offset)) -#define MAP_FIELD_PTR(msg, offset) ((CGPMapField *)((uint8_t *)msg + offset)) +CGP_ALWAYS_INLINE CGPRepeatedField *REPEATED_FIELD_PTR(id msg, ptrdiff_t offset) { + return (CGPRepeatedField *)((uint8_t *)msg + offset); +} +CGP_ALWAYS_INLINE CGPMapField *MAP_FIELD_PTR(id msg, ptrdiff_t offset) { + return (CGPMapField *)((uint8_t *)msg + offset); +} #define FIELD_PTR(TYPE, msg, offset) ((TYPE *)((uint8_t *)msg + offset)) #define SINGULAR_SETTER_IMP(NAME) \ static void SingularSet##NAME(id msg, TYPE_##NAME value, size_t offset, CGPHasLocator hasLoc) { \ TYPE_##NAME *ptr = FIELD_PTR(TYPE_##NAME, msg, offset); \ ClearPreviousOneof(msg, hasLoc, (uintptr_t)ptr); \ - TYPE_ASSIGN_##NAME(*ptr, value); \ + TYPE_ASSIGN_##NAME(ptr, value); \ SetHas(msg, hasLoc); \ } -FOR_EACH_TYPE_NO_RETAINABLE(SINGULAR_SETTER_IMP) +FOR_EACH_PRIMITIVE_TYPE(SINGULAR_SETTER_IMP) -static void SingularSetRetainable(id msg, TYPE_Retainable value, size_t offset, - CGPHasLocator hasLoc) { - TYPE_Retainable *ptr = FIELD_PTR(TYPE_Retainable, msg, offset); +static void SingularSetId(id msg, TYPE_Id value, size_t offset, CGPHasLocator hasLoc) { + TYPE_Id *ptr = FIELD_PTR(TYPE_Id, msg, offset); + if (!ClearPreviousOneof(msg, hasLoc, (uintptr_t)ptr)) { + // If it is not a one of field, we need to release the previous value. + // Otherwise ClearPreviousOneof has already done it for us if necessary. + AUTORELEASE(*ptr); + } + *ptr = RETAIN_(value); + SetHas(msg, hasLoc); +} + +static void SingularSetEnum(id msg, TYPE_Enum value, size_t offset, CGPHasLocator hasLoc) { + TYPE_Enum *ptr = FIELD_PTR(TYPE_Enum, msg, offset); if (!ClearPreviousOneof(msg, hasLoc, (uintptr_t)ptr)) { // If it is not a one of field, we need to release the previous value. // Otherwise ClearPreviousOneof has already done it for us if necessary. @@ -334,43 +332,30 @@ static void SingularSetRetainable(id msg, TYPE_Retainable value, size_t offset, // ********** Dynamic field accessors ****************************************** // ***************************************************************************** -#define SINGULAR_PRIMITIVE_GETTER_IMP(NAME) \ - static IMP GetSingularGetterImp##NAME(size_t offset, CGPHasLocator hasLoc, \ - TYPE_##NAME defaultValue) { \ - return imp_implementationWithBlock(^TYPE_##NAME(id msg) { \ - if (GetHas(msg, hasLoc)) { \ - return *FIELD_PTR(TYPE_##NAME, msg, offset); \ - } \ - return defaultValue; \ - }); \ - } - -#define SINGULAR_RETAINABLE_GETTER_IMP(NAME) \ - static IMP GetSingularGetterImp##NAME(size_t offset, CGPHasLocator hasLoc, \ - TYPE_##NAME defaultValue) { \ - return imp_implementationWithBlock(^TYPE_##NAME(id msg) { \ - if (GetHas(msg, hasLoc)) { \ - return RETAIN_AND_AUTORELEASE(*FIELD_PTR(TYPE_##NAME, msg, offset)); \ - } \ - return defaultValue; \ - }); \ +#define SINGULAR_GETTER_IMP(NAME) \ + static IMP GetSingularGetterImp##NAME(size_t offset, CGPHasLocator hasLoc, \ + TYPE_##NAME defaultValue) { \ + return imp_implementationWithBlock(^EXTERNAL_TYPE_##NAME(id msg) { \ + TYPE_##NAME value = \ + GetHas(msg, hasLoc) ? *FIELD_PTR(TYPE_##NAME, msg, offset) : defaultValue; \ + return ToExternalType##NAME(value); \ + }); \ } -FOR_EACH_TYPE_NO_ENUM(SINGULAR_PRIMITIVE_GETTER_IMP, SINGULAR_RETAINABLE_GETTER_IMP) +FOR_EACH_TYPE(SINGULAR_GETTER_IMP) -#undef SINGULAR_PRIMITIVE_GETTER_IMP -#undef SINGULAR_RETAINABLE_GETTER_IMP +#undef SINGULAR_GETTER_IMP -#define REPEATED_GETTER_IMP(NAME) \ - static IMP GetRepeatedGetterImp##NAME(size_t offset) { \ - return imp_implementationWithBlock(^TYPE_##NAME(id msg, jint idx) { \ - return CGPRepeatedFieldGet##NAME(REPEATED_FIELD_PTR(msg, offset), idx); \ - }); \ +#define REPEATED_GETTER_IMP(NAME) \ + static IMP GetRepeatedGetterImp##NAME(size_t offset) { \ + return imp_implementationWithBlock(^EXTERNAL_TYPE_##NAME(id msg, jint idx) { \ + CGPRepeatedField *field = REPEATED_FIELD_PTR(msg, offset); \ + CGPRepeatedFieldCheckBounds(field, idx); \ + return ToExternalType##NAME(((TYPE_##NAME *)field->data->buffer)[idx]); \ + }); \ } -// Same macro for all types, uses getter functions defined earlier that -// already handle primitive vs retainable. -FOR_EACH_TYPE_NO_ENUM(REPEATED_GETTER_IMP, REPEATED_GETTER_IMP) +FOR_EACH_TYPE(REPEATED_GETTER_IMP) #undef REPEATED_GETTER_IMP @@ -381,14 +366,13 @@ static BOOL AddGetterMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { size_t offset = CGPFieldGetOffset(field, cls); CGPHasLocator hasLoc = GetHasLocator(cls, field); -#define ADD_GETTER_METHOD_CASE(NAME) \ - imp = repeated \ - ? GetRepeatedGetterImp##NAME(offset) \ - : GetSingularGetterImp##NAME(offset, hasLoc, field->data_->defaultValue.value##NAME); \ - strcpy(encoding, @encode(TYPE_##NAME)); \ - break; +#define ADD_GETTER_METHOD_CASE(NAME) \ + imp = repeated ? GetRepeatedGetterImp##NAME(offset) \ + : GetSingularGetterImp##NAME(offset, hasLoc, \ + CGPFieldGetDefaultValue(field).value##NAME); \ + strcpy(encoding, @encode(TYPE_##NAME)); - SWITCH_TYPES_NO_ENUM(CGPFieldGetJavaType(field), ADD_GETTER_METHOD_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), ADD_GETTER_METHOD_CASE) #undef ADD_GETTER_METHOD_CASE @@ -505,28 +489,31 @@ static BOOL AddClearMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { return class_addMethod(cls, sel, imp, "@@:"); } -#define GET_SINGULAR_SETTER_IMP(NAME) \ - static IMP GetSingularSetterImp##NAME(size_t offset, CGPHasLocator hasLoc) { \ - return imp_implementationWithBlock(^id(id msg, TYPE_##NAME value) { \ - NIL_CHECK_##NAME(value) SingularSet##NAME(msg, value, offset, hasLoc); \ - return msg; \ - }); \ +#define GET_SINGULAR_SETTER_IMP(NAME) \ + static IMP GetSingularSetterImp##NAME(size_t offset, CGPHasLocator hasLoc) { \ + return imp_implementationWithBlock(^id(id msg, EXTERNAL_TYPE_##NAME value) { \ + NIL_CHECK_##NAME(value); \ + TYPE_##NAME internalValue = ToType##NAME(value); \ + SingularSet##NAME(msg, internalValue, offset, hasLoc); \ + return msg; \ + }); \ } -FOR_EACH_TYPE_WITH_ENUM(GET_SINGULAR_SETTER_IMP) +FOR_EACH_TYPE(GET_SINGULAR_SETTER_IMP) #undef GET_SINGULAR_SETTER_IMP -#define GET_REPEATED_SETTER_IMP(NAME) \ - static IMP GetRepeatedSetterImp##NAME(size_t offset) { \ - return imp_implementationWithBlock(^id(id msg, jint idx, TYPE_##NAME value) { \ - NIL_CHECK_##NAME(value) \ - CGPRepeatedFieldSet##NAME(REPEATED_FIELD_PTR(msg, offset), idx, value); \ - return msg; \ - }); \ +#define GET_REPEATED_SETTER_IMP(NAME) \ + static IMP GetRepeatedSetterImp##NAME(size_t offset) { \ + return imp_implementationWithBlock(^id(id msg, jint idx, EXTERNAL_TYPE_##NAME value) { \ + NIL_CHECK_##NAME(value); \ + TYPE_##NAME internalValue = ToType##NAME(value); \ + CGPRepeatedFieldSet##NAME(REPEATED_FIELD_PTR(msg, offset), idx, internalValue); \ + return msg; \ + }); \ } -FOR_EACH_TYPE_WITH_ENUM(GET_REPEATED_SETTER_IMP) +FOR_EACH_TYPE(GET_REPEATED_SETTER_IMP) #undef GET_REPEATED_SETTER_IMP @@ -543,10 +530,9 @@ static BOOL AddSetterMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { #define ADD_SETTER_METHOD_CASE(NAME) \ imp = repeated ? GetRepeatedSetterImp##NAME(offset) \ : GetSingularSetterImp##NAME(offset, GetHasLocator(cls, field)); \ - strcat(encoding, @encode(TYPE_##NAME)); \ - break; + strcat(encoding, @encode(TYPE_##NAME)); - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(field), ADD_SETTER_METHOD_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), ADD_SETTER_METHOD_CASE) #undef ADD_SETTER_METHOD_CASE @@ -572,15 +558,17 @@ static BOOL AddBuilderSetterMethod(Class cls, SEL sel, CGPFieldDescriptor *field return class_addMethod(cls, sel, imp, "@@:@"); } -#define GET_ADDER_IMP(NAME) \ - static IMP GetAdderImp##NAME(size_t offset) { \ - return imp_implementationWithBlock(^id(id msg, TYPE_##NAME value) { \ - NIL_CHECK_##NAME(value) CGPRepeatedFieldAdd##NAME(REPEATED_FIELD_PTR(msg, offset), value); \ - return msg; \ - }); \ +#define GET_ADDER_IMP(NAME) \ + static IMP GetAdderImp##NAME(size_t offset) { \ + return imp_implementationWithBlock(^id(id msg, EXTERNAL_TYPE_##NAME value) { \ + NIL_CHECK_##NAME(value); \ + TYPE_##NAME internalValue = ToType##NAME(value); \ + CGPRepeatedFieldAdd##NAME(REPEATED_FIELD_PTR(msg, offset), internalValue); \ + return msg; \ + }); \ } -FOR_EACH_TYPE_WITH_ENUM(GET_ADDER_IMP) +FOR_EACH_TYPE(GET_ADDER_IMP) #undef GET_ADDER_IMP @@ -590,12 +578,11 @@ static BOOL AddAdderMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { strcpy(encoding, "@@:"); size_t offset = CGPFieldGetOffset(field, cls); -#define ADD_ADDER_METHOD_CASE(NAME) \ - imp = GetAdderImp##NAME(offset); \ - strcat(encoding, @encode(TYPE_##NAME)); \ - break; +#define ADD_ADDER_METHOD_CASE(NAME) \ + imp = GetAdderImp##NAME(offset); \ + strcat(encoding, @encode(TYPE_##NAME)); - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(field), ADD_ADDER_METHOD_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), ADD_ADDER_METHOD_CASE) #undef ADD_ADDER_METHOD_CASE @@ -607,7 +594,7 @@ static BOOL AddBuilderAdderMethod(Class cls, SEL sel, CGPFieldDescriptor *field) IMP imp = imp_implementationWithBlock(^id(id msg, ComGoogleProtobufGeneratedMessage_Builder *value) { (void)nil_chk(value); - CGPRepeatedFieldAddRetainable(REPEATED_FIELD_PTR(msg, offset), [value build]); + CGPRepeatedFieldAddId(REPEATED_FIELD_PTR(msg, offset), [value build]); return msg; }); return class_addMethod(cls, sel, imp, "@@:@"); @@ -624,7 +611,7 @@ static BOOL AddBuilderAdderMethod(Class cls, SEL sel, CGPFieldDescriptor *field) }); \ } -FOR_EACH_TYPE_WITH_ENUM(GET_ADD_ALL_IMP) +FOR_EACH_TYPE(GET_ADD_ALL_IMP) #undef GET_ADD_ALL_IMP @@ -632,11 +619,9 @@ static BOOL AddAddAllMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { IMP imp = NULL; size_t offset = CGPFieldGetOffset(field, cls); -#define ADD_ALL_METHOD_CASE(NAME) \ - imp = GetAddAllImp##NAME(offset); \ - break; +#define ADD_ALL_METHOD_CASE(NAME) imp = GetAddAllImp##NAME(offset); - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(field), ADD_ALL_METHOD_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), ADD_ALL_METHOD_CASE) #undef ADD_ALL_METHOD_CASE @@ -646,9 +631,9 @@ static BOOL AddAddAllMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { #define GET_CONTAINS_IMP(NAME) \ static IMP GetContainsImp##NAME(size_t offset, CGPFieldJavaType keyType, \ CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock(^bool(id msg, TYPE_##NAME pKey) { \ + return imp_implementationWithBlock(^bool(id msg, EXTERNAL_TYPE_##NAME pKey) { \ CGPValue key; \ - key.CGPValueField_##NAME = pKey; \ + key.CGPValueField_##NAME = ToType##NAME(pKey); \ return CGPMapFieldGetWithKey(MAP_FIELD_PTR(msg, offset), key, keyType, valueType) != nil; \ }); \ } @@ -696,83 +681,46 @@ static BOOL AddContainsMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { return class_addMethod(cls, sel, imp, encoding); } -#define GET_MAP_PRIMITIVE_GETTER_IMP(KEY_NAME, VALUE_NAME) \ +#define GET_MAP_GETTER_IMP(KEY_NAME, VALUE_NAME) \ static IMP GetMapGetOrThrowImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock(^TYPE_##VALUE_NAME(id msg, TYPE_##KEY_NAME pKey) { \ - CGPValue key; \ - key.CGPValueField_##KEY_NAME = pKey; \ - CGPMapFieldEntry *entry = \ - CGPMapFieldGetWithKey(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ - if (entry) { \ - return entry->value.CGPValueField_##VALUE_NAME; \ - } \ - @throw create_JavaLangIllegalArgumentException_init(); \ - }); \ - } \ - static IMP GetMapGetOrDefaultImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ - CGPFieldJavaType valueType) { \ return imp_implementationWithBlock( \ - ^TYPE_##VALUE_NAME(id msg, TYPE_##KEY_NAME pKey, TYPE_##VALUE_NAME defaultValue) { \ + ^EXTERNAL_TYPE_##VALUE_NAME(id msg, EXTERNAL_TYPE_##KEY_NAME pKey) { \ CGPValue key; \ - key.CGPValueField_##KEY_NAME = pKey; \ + key.CGPValueField_##KEY_NAME = ToType##KEY_NAME(pKey); \ CGPMapFieldEntry *entry = \ CGPMapFieldGetWithKey(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ if (entry) { \ - return entry->value.CGPValueField_##VALUE_NAME; \ + return ToExternalType##VALUE_NAME(entry->value.CGPValueField_##VALUE_NAME); \ } \ - return defaultValue; \ + @throw create_JavaLangIllegalArgumentException_init(); \ }); \ - } - -#define GET_MAP_RETAINABLE_GETTER_IMP(KEY_NAME, VALUE_NAME) \ - static IMP GetMapGetOrThrowImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ - CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock(^TYPE_##VALUE_NAME(id msg, TYPE_##KEY_NAME pKey) { \ + } \ + static IMP GetMapGetOrDefaultImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ + CGPFieldJavaType valueType) { \ + return imp_implementationWithBlock(^EXTERNAL_TYPE_##VALUE_NAME( \ + id msg, EXTERNAL_TYPE_##KEY_NAME pKey, TYPE_##VALUE_NAME defaultValue) { \ CGPValue key; \ - key.CGPValueField_##KEY_NAME = pKey; \ + key.CGPValueField_##KEY_NAME = ToType##KEY_NAME(pKey); \ CGPMapFieldEntry *entry = \ CGPMapFieldGetWithKey(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ if (entry) { \ - return RETAIN_AND_AUTORELEASE(entry->value.CGPValueField_##VALUE_NAME); \ + return ToExternalType##VALUE_NAME(entry->value.CGPValueField_##VALUE_NAME); \ } \ - @throw create_JavaLangIllegalArgumentException_init(); \ + return ToExternalType##VALUE_NAME(defaultValue); \ }); \ - } \ - static IMP GetMapGetOrDefaultImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ - CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock( \ - ^TYPE_##VALUE_NAME(id msg, TYPE_##KEY_NAME pKey, TYPE_##VALUE_NAME defaultValue) { \ - CGPValue key; \ - key.CGPValueField_##KEY_NAME = pKey; \ - CGPMapFieldEntry *entry = \ - CGPMapFieldGetWithKey(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ - if (entry) { \ - return RETAIN_AND_AUTORELEASE(entry->value.CGPValueField_##VALUE_NAME); \ - } \ - return defaultValue; \ - }); \ } -#define GET_MAP_PRIMITIVE_GETTER_IMP_FOR_VALUE(VALUE_NAME) \ - GET_MAP_PRIMITIVE_GETTER_IMP(Int, VALUE_NAME) \ - GET_MAP_PRIMITIVE_GETTER_IMP(Long, VALUE_NAME) \ - GET_MAP_PRIMITIVE_GETTER_IMP(Bool, VALUE_NAME) \ - GET_MAP_PRIMITIVE_GETTER_IMP(Id, VALUE_NAME) +#define GET_MAP_GETTER_IMP_FOR_VALUE(VALUE_NAME) \ + GET_MAP_GETTER_IMP(Int, VALUE_NAME) \ + GET_MAP_GETTER_IMP(Long, VALUE_NAME) \ + GET_MAP_GETTER_IMP(Bool, VALUE_NAME) \ + GET_MAP_GETTER_IMP(Id, VALUE_NAME) -#define GET_MAP_RETAINABLE_GETTER_IMP_FOR_VALUE(VALUE_NAME) \ - GET_MAP_RETAINABLE_GETTER_IMP(Int, VALUE_NAME) \ - GET_MAP_RETAINABLE_GETTER_IMP(Long, VALUE_NAME) \ - GET_MAP_RETAINABLE_GETTER_IMP(Bool, VALUE_NAME) \ - GET_MAP_RETAINABLE_GETTER_IMP(Id, VALUE_NAME) +FOR_EACH_TYPE(GET_MAP_GETTER_IMP_FOR_VALUE) -FOR_EACH_TYPE_NO_ENUM(GET_MAP_PRIMITIVE_GETTER_IMP_FOR_VALUE, - GET_MAP_RETAINABLE_GETTER_IMP_FOR_VALUE) - -#undef GET_MAP_PRIMITIVE_GETTER_IMP -#undef GET_MAP_RETAINABLE_GETTER_IMP -#undef GET_MAP_PRIMITIVE_GETTER_IMP_FOR_VALUE -#undef GET_MAP_RETAINABLE_GETTER_IMP_FOR_VALUE +#undef GET_MAP_GETTER_IMP +#undef GET_MAP_GETTER_IMP_FOR_VALUE static BOOL AddMapGetWithKeyMethod(Class cls, SEL sel, CGPFieldDescriptor *field, bool orDefault) { IMP imp = NULL; @@ -808,10 +756,9 @@ static BOOL AddMapGetWithKeyMethod(Class cls, SEL sel, CGPFieldDescriptor *field } \ if (orDefault) { \ strcat(encoding, @encode(TYPE_##VALUE_NAME)); \ - } \ - break; + } - SWITCH_TYPES_NO_ENUM(valueType, MAP_GETTER_INNER_SWITCH) + SWITCH_TYPES(valueType, MAP_GETTER_INNER_SWITCH) #undef MAP_GETTER_CASE #undef MAP_GETTER_INNER_SWITCH @@ -819,19 +766,19 @@ static BOOL AddMapGetWithKeyMethod(Class cls, SEL sel, CGPFieldDescriptor *field return class_addMethod(cls, sel, imp, encoding); } -#define GET_PUT_IMP(KEY_NAME, VALUE_NAME) \ - static IMP GetPutImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ - CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock( \ - ^id(id msg, TYPE_##KEY_NAME pKey, TYPE_##VALUE_NAME pValue) { \ - CGPValue key; \ - key.CGPValueField_##KEY_NAME = pKey; \ - CGPValue value; \ - value.CGPValueField_##VALUE_NAME = pValue; \ - CGPMapFieldPut(MAP_FIELD_PTR(msg, offset), key, keyType, value, valueType, \ - /* retainedKeyAndValue */ false); \ - return msg; \ - }); \ +#define GET_PUT_IMP(KEY_NAME, VALUE_NAME) \ + static IMP GetPutImp##KEY_NAME##VALUE_NAME(size_t offset, CGPFieldJavaType keyType, \ + CGPFieldJavaType valueType) { \ + return imp_implementationWithBlock( \ + ^id(id msg, EXTERNAL_TYPE_##KEY_NAME pKey, EXTERNAL_TYPE_##VALUE_NAME pValue) { \ + CGPValue key; \ + key.CGPValueField_##KEY_NAME = ToType##KEY_NAME(pKey); \ + CGPValue value; \ + value.CGPValueField_##VALUE_NAME = ToType##VALUE_NAME(pValue); \ + CGPMapFieldPut(MAP_FIELD_PTR(msg, offset), key, keyType, value, valueType, \ + /* retainedKeyAndValue */ false); \ + return msg; \ + }); \ } #define GET_PUT_IMP_FOR_VALUE(VALUE_NAME) \ @@ -841,7 +788,7 @@ static BOOL AddMapGetWithKeyMethod(Class cls, SEL sel, CGPFieldDescriptor *field GET_PUT_IMP(Id, VALUE_NAME) // No difference in put implementation by type, CGPMapFieldPut() handles both types. -FOR_EACH_TYPE_NO_ENUM(GET_PUT_IMP_FOR_VALUE, GET_PUT_IMP_FOR_VALUE) +FOR_EACH_TYPE(GET_PUT_IMP_FOR_VALUE) #undef GET_PUT_IMP #undef GET_PUT_IMP_FOR_VALUE @@ -876,10 +823,9 @@ static BOOL AddPutMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: \ return NO; \ } \ - strcat(encoding, @encode(TYPE_##VALUE_NAME)); \ - break; + strcat(encoding, @encode(TYPE_##VALUE_NAME)); - SWITCH_TYPES_NO_ENUM(valueType, PUT_METHOD_INNER_SWITCH) + SWITCH_TYPES(valueType, PUT_METHOD_INNER_SWITCH) #undef PUT_METHOD_CASE #undef PUT_METHOD_INNER_SWITCH @@ -887,15 +833,15 @@ static BOOL AddPutMethod(Class cls, SEL sel, CGPFieldDescriptor *field) { return class_addMethod(cls, sel, imp, encoding); } -#define GET_MAP_REMOVE_IMP(NAME) \ - static IMP GetMapRemoveImp##NAME(size_t offset, CGPFieldJavaType keyType, \ - CGPFieldJavaType valueType) { \ - return imp_implementationWithBlock(^id(id msg, TYPE_##NAME pKey) { \ - CGPValue key; \ - key.CGPValueField_##NAME = pKey; \ - CGPMapFieldRemove(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ - return msg; \ - }); \ +#define GET_MAP_REMOVE_IMP(NAME) \ + static IMP GetMapRemoveImp##NAME(size_t offset, CGPFieldJavaType keyType, \ + CGPFieldJavaType valueType) { \ + return imp_implementationWithBlock(^id(id msg, EXTERNAL_TYPE_##NAME pKey) { \ + CGPValue key; \ + key.CGPValueField_##NAME = ToType##NAME(pKey); \ + CGPMapFieldRemove(MAP_FIELD_PTR(msg, offset), key, keyType, valueType); \ + return msg; \ + }); \ } GET_MAP_REMOVE_IMP(Int) @@ -1296,14 +1242,14 @@ static id GetSingularField(id msg, CGPFieldDescriptor *field) { bool isSet = GetHas(msg, GetHasLocator(msgCls, field)); size_t offset = CGPFieldGetOffset(field, msgCls); -#define GET_FIELD_CASE(NAME) \ - { \ - TYPE_##NAME value = isSet ? *FIELD_PTR(TYPE_##NAME, msg, offset) \ - : field->data_->defaultValue.CGPValueField_##NAME; \ - return CGPToReflectionType##NAME(value, field); \ +#define GET_FIELD_CASE(NAME) \ + { \ + TYPE_##NAME value = isSet ? *FIELD_PTR(TYPE_##NAME, msg, offset) \ + : CGPFieldGetDefaultValue(field).CGPValueField_##NAME; \ + return CGPToReflectionType##NAME(value); \ } - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(field), GET_FIELD_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), GET_FIELD_CASE) #undef GET_FIELD_CASE @@ -1501,13 +1447,10 @@ static void MergeFieldsFromMessage(id msg, id other, CGPDescriptor *descriptor) } ClearPreviousOneof(msg, hasLoc, fieldPtr); -#define MERGE_FIELD_CASE(NAME) \ - { \ - TYPE_ASSIGN_##NAME(*(TYPE_##NAME *)fieldPtr, *(TYPE_##NAME *)otherFieldPtr); \ - break; \ - } +#define MERGE_FIELD_CASE(NAME) \ + TYPE_ASSIGN_##NAME((TYPE_##NAME *)fieldPtr, *(TYPE_##NAME *)otherFieldPtr); - SWITCH_TYPES_WITH_ENUM(type, MERGE_FIELD_CASE) + SWITCH_TYPES(type, MERGE_FIELD_CASE) #undef MERGE_FIELD_CASE @@ -1572,21 +1515,13 @@ static id DynamicMergeFromMessage(id builder, SEL _cmd, id other) { // ***************************************************************************** static inline BOOL ReadEnumValueDescriptor(CGPCodedInputStream *input, CGPEnumDescriptor *enumType, - id *valueDescriptor) { + CGPEnumValueDescriptor **valueDescriptor) { jint value; if (!CGPReadEnum(input, &value)) return NO; *valueDescriptor = CGPEnumValueDescriptorFromInt(enumType, value); return YES; } -static BOOL ReadEnumJavaValue(CGPCodedInputStream *input, CGPEnumDescriptor *enumType, - id *javaValue) { - CGPEnumValueDescriptor *valueDescriptor; - if (!ReadEnumValueDescriptor(input, enumType, &valueDescriptor)) return NO; - *javaValue = valueDescriptor == nil ? nil : valueDescriptor->enum_; - return YES; -} - static inline BOOL MergeGroupFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInputStream *input, CGPExtensionRegistryLite *registry) { @@ -1642,8 +1577,16 @@ static BOOL ReadMapEntryField(CGPCodedInputStream *stream, CGPFieldDescriptor *f return CGPReadFloat(stream, &value->valueFloat); case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_DOUBLE: return CGPReadDouble(stream, &value->valueDouble); - case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: - return ReadEnumJavaValue(stream, field->valueType_, &value->valueId) && value->valueId != nil; + case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: { + CGPEnumValueDescriptor *enumValueDescriptor; + BOOL result = ReadEnumValueDescriptor(stream, field->valueType_, &enumValueDescriptor); + if (result && enumValueDescriptor != nil) { + value->valueEnum = RETAIN_(enumValueDescriptor); + return YES; + } else { + return NO; + } + } case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_BYTES: return stream->ReadRetainedByteString(&value->valueId); case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_STRING: @@ -1726,7 +1669,7 @@ static BOOL MergeExtensionValueFromStream(CGPCodedInputStream *stream, CGPFieldD case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_##ENUM_NAME: { \ TYPE_##JAVA_NAME value; \ if (!CGPRead##WIRE_NAME(stream, &value)) return NO; \ - *result = CGPToReflectionType##JAVA_NAME(value, field); \ + *result = CGPToReflectionType##JAVA_NAME(value); \ *isRetained = NO; \ return YES; \ } @@ -1914,8 +1857,7 @@ static BOOL MergeFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInpu BOOL alreadyCleared = NO; if (!repeated) { hasLoc = GetHasLocator(msgCls, field); - ClearPreviousOneof(msg, hasLoc, fieldPtr); - alreadyCleared = YES; + alreadyCleared = ClearPreviousOneof(msg, hasLoc, fieldPtr); } switch (CGPFieldGetType(field)) { #define MERGE_FIELD_CASE(NAME, ENUM_NAME, JAVA_NAME) \ @@ -1967,22 +1909,26 @@ static BOOL MergeFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInpu CGPRepeatedFieldReserveAdditionalCapacity(repeatedField, length, sizeof(id)); CGPCodedInputStream::Limit limit = stream->PushLimit(length); while (stream->BytesUntilLimit() > 0) { - if (!ReadEnumJavaValue(stream, enumType, &value)) return NO; + if (!ReadEnumValueDescriptor(stream, enumType, &value)) return NO; if (value != nil) { CGPRepeatedFieldAddEnum(repeatedField, value); } } stream->PopLimit(limit); } else { - if (!ReadEnumJavaValue(stream, enumType, &value)) return NO; + if (!ReadEnumValueDescriptor(stream, enumType, &value)) return NO; if (value != nil) { CGPRepeatedFieldAddEnum(repeatedField, value); } } } else { - if (!ReadEnumJavaValue(stream, enumType, &value)) return NO; + if (!ReadEnumValueDescriptor(stream, enumType, &value)) return NO; if (value == nil) return YES; // Skip setting has-bit. - *(id *)fieldPtr = value; + id *ptr = (id *)fieldPtr; + if (!alreadyCleared) { + AUTORELEASE(*ptr); + } + *ptr = RETAIN_(value); SetHas(msg, hasLoc); } } @@ -1991,7 +1937,8 @@ static BOOL MergeFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInpu CGPByteString *value; if (!stream->ReadRetainedByteString(&value)) return NO; if (repeated) { - CGPRepeatedFieldAddRetainedId((CGPRepeatedField *)fieldPtr, value); + CGPRepeatedFieldAddId((CGPRepeatedField *)fieldPtr, value); + RELEASE_(value); } else { id *ptr = (id *)fieldPtr; if (!alreadyCleared) { @@ -2006,7 +1953,8 @@ static BOOL MergeFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInpu NSString *value; if (!stream->ReadRetainedNSString(&value)) return NO; if (repeated) { - CGPRepeatedFieldAddRetainedId((CGPRepeatedField *)fieldPtr, value); + CGPRepeatedFieldAddId((CGPRepeatedField *)fieldPtr, value); + RELEASE_(value); } else { id *ptr = (id *)fieldPtr; if (!alreadyCleared) { @@ -2027,7 +1975,8 @@ static BOOL MergeFieldFromStream(id msg, CGPFieldDescriptor *field, CGPCodedInpu } ComGoogleProtobufGeneratedMessage *msgField = CGPNewMessage(fieldType); if (repeated) { - CGPRepeatedFieldAddRetainedId((CGPRepeatedField *)fieldPtr, msgField); + CGPRepeatedFieldAddId((CGPRepeatedField *)fieldPtr, msgField); + RELEASE_(msgField); } else { id *ptr = (id *)fieldPtr; if (GetHas(msg, hasLoc)) { @@ -2266,7 +2215,7 @@ static int SerializedSizeForMapEntryField(CGPFieldDescriptor *field, CGPValue va case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_BOOL: return tagSize + 1; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: - return tagSize + CGPGetEnumSize(CGPEnumGetIntValue(field->valueType_, value.valueId)); + return tagSize + CGPGetEnumSize(CGPEnumGetIntValue(field->valueType_, value.valueEnum)); case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_BYTES: return tagSize + CGPGetBytesSize(value.valueId); case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_STRING: @@ -2348,7 +2297,7 @@ static int SerializedSizeForRepeatedField(id msg, CGPFieldDescriptor *field) { break; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: { CGPEnumDescriptor *enumType = field->valueType_; - id *buffer = (id *)data->buffer; + TYPE_Enum *buffer = (TYPE_Enum *)data->buffer; for (uint32_t i = 0; i < arrayLen; i++) { arraySize += CGPGetEnumSize(CGPEnumGetIntValue(enumType, buffer[i])); } @@ -2496,8 +2445,8 @@ static void WriteSingularExtensionValue(CGPFieldDescriptor *field, id value, WRITE_SINGULAR_EXTENSION_CASE(Bool, BOOL, Bool) WRITE_SINGULAR_EXTENSION_CASE(Float, FLOAT, Float) WRITE_SINGULAR_EXTENSION_CASE(Double, DOUBLE, Double) - WRITE_SINGULAR_EXTENSION_CASE(Bytes, BYTES, Retainable) - WRITE_SINGULAR_EXTENSION_CASE(String, STRING, Retainable) + WRITE_SINGULAR_EXTENSION_CASE(Bytes, BYTES, Id) + WRITE_SINGULAR_EXTENSION_CASE(String, STRING, Id) case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: CGPWriteEnum(((CGPEnumValueDescriptor *)value)->number_, output); return; @@ -2640,7 +2589,7 @@ static void WriteMapEntryField(CGPFieldDescriptor *field, CGPValue value, CGPWriteDouble(value.valueDouble, output); return; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: - CGPWriteEnum(CGPEnumGetIntValue(field->valueType_, value.valueId), output); + CGPWriteEnum(CGPEnumGetIntValue(field->valueType_, value.valueEnum), output); return; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_BYTES: CGPWriteBytes(value.valueId, output); @@ -2743,7 +2692,7 @@ static void WriteRepeatedField(id msg, CGPFieldDescriptor *field, CGPCodedOutput WRITE_REPEATED_FIELD_FIXED_LENGTH_CASE(Float, FLOAT, Float, sizeof(uint32_t)) WRITE_REPEATED_FIELD_FIXED_LENGTH_CASE(Double, DOUBLE, Double, sizeof(uint64_t)) case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: { - id *buffer = (id *)data->buffer; + TYPE_Enum *buffer = (TYPE_Enum *)data->buffer; CGPEnumDescriptor *enumType = field->valueType_; if (CGPFieldIsPacked(field)) { std::vector intValues(arrayLen); @@ -3041,7 +2990,7 @@ void ValueToString(CGPValue value, CGPFieldDescriptor *field, NSMutableString *b [builder appendFormat:@"%s%s: %g\n", padding, fieldName, value.valueDouble]; return; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_ENUM: - [builder appendFormat:@"%s%s: %@\n", padding, fieldName, value.valueId]; + [builder appendFormat:@"%s%s: %@\n", padding, fieldName, value.valueEnum]; return; case ComGoogleProtobufDescriptors_FieldDescriptor_Type_Enum_BYTES: [builder appendFormat:@"%s%s: %@\n", padding, fieldName, BytesToString(value.valueId)]; @@ -3193,20 +3142,20 @@ static void MessageToString(id msg, CGPDescriptor *descriptor, NSMutableString * // ********** isEqual and hash ************************************************* // ***************************************************************************** -#define FieldIsEqualInt(a, b) a == b -#define FieldIsEqualLong(a, b) a == b -#define FieldIsEqualFloat(a, b) a == b -#define FieldIsEqualDouble(a, b) a == b -#define FieldIsEqualBool(a, b) a == b -#define FieldIsEqualEnum(a, b) a == b -#define FieldIsEqualRetainable(a, b) a == b || [a isEqual:b] +CGP_ALWAYS_INLINE BOOL FieldIsEqualInt(jint a, jint b) { return a == b; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualLong(jlong a, jlong b) { return a == b; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualFloat(jfloat a, jfloat b) { return a == b; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualDouble(jdouble a, jdouble b) { return a == b; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualBool(bool a, bool b) { return a == b; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualEnum(id a, id b) { return a == b || [a isEqual:b]; } +CGP_ALWAYS_INLINE BOOL FieldIsEqualId(id a, id b) { return a == b || [a isEqual:b]; } static BOOL FieldIsEqual(id self, id other, size_t offset, CGPFieldJavaType type) { #define IS_FIELD_EQUAL_CASE(NAME) \ return FieldIsEqual##NAME(*FIELD_PTR(TYPE_##NAME, self, offset), \ *FIELD_PTR(TYPE_##NAME, other, offset)); - SWITCH_TYPES_WITH_ENUM(type, IS_FIELD_EQUAL_CASE) + SWITCH_TYPES(type, IS_FIELD_EQUAL_CASE) #undef IS_FIELD_EQUAL_CASE @@ -3290,10 +3239,9 @@ static int RepeatedFieldHash(id msg, CGPFieldDescriptor *field, int hash) { TYPE_##NAME value = buffer[i]; \ hash = 31 * hash + HASH_##NAME(value); \ } \ - } \ - break; + } - SWITCH_TYPES_NO_ENUM(CGPFieldGetJavaType(field), REPEATED_FIELD_HASH_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), REPEATED_FIELD_HASH_CASE) #undef REPEATED_FIELD_HASH_CASE @@ -3314,7 +3262,7 @@ static int SingularFieldHash(id msg, CGPFieldDescriptor *field, int hash) { return 53 * hash + HASH_##NAME(value); \ } - SWITCH_TYPES_NO_ENUM(CGPFieldGetJavaType(field), SINGULAR_FIELD_HASH_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(field), SINGULAR_FIELD_HASH_CASE) #undef SINGULAR_FIELD_HASH_CASE @@ -3697,11 +3645,10 @@ - (id)getRepeatedFieldWithComGoogleProtobufDescriptors_FieldDescriptor: } else { CGPHasLocator hasLoc = GetHasLocator(cls, descriptor); -#define SET_SINGULAR_FIELD_CASE(NAME) \ - SingularSet##NAME(self, CGPFromReflectionType##NAME(object), offset, hasLoc); \ - break; +#define SET_SINGULAR_FIELD_CASE(NAME) \ + SingularSet##NAME(self, CGPFromReflectionType##NAME(object), offset, hasLoc); - SWITCH_TYPES_WITH_ENUM(javaType, SET_SINGULAR_FIELD_CASE) + SWITCH_TYPES(javaType, SET_SINGULAR_FIELD_CASE) #undef SET_SINGULAR_FIELD_CASE } @@ -3950,7 +3897,7 @@ static id GetSingularExtension(CGPExtensionMap *extensionMap, if (it != extensionMap->end()) { value = it->second.get(); } else { - value = CGPFieldGetDefaultValue(field); + value = CGPFieldGetDefaultValueObject(field); } return FromReflectionType(field, value); } diff --git a/protobuf/runtime/src/com/google/protobuf/MapField.m b/protobuf/runtime/src/com/google/protobuf/MapField.m index 5af34ab0e8..bd5c6e55d0 100644 --- a/protobuf/runtime/src/com/google/protobuf/MapField.m +++ b/protobuf/runtime/src/com/google/protobuf/MapField.m @@ -50,7 +50,7 @@ static uint32_t Hash0(CGPValue value, CGPFieldJavaType type) { #define HASH_CASE(NAME) return HASH_##NAME(value.CGPValueField_##NAME); -SWITCH_TYPES_NO_ENUM(type, HASH_CASE) + SWITCH_TYPES(type, HASH_CASE) #undef HASH_CASE } @@ -76,7 +76,7 @@ static bool Equals(CGPValue a, CGPValue b, CGPFieldJavaType type) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: return a.valueBool == b.valueBool; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: - return a.valueId == b.valueId; + return [a.valueEnum isEqual:b.valueEnum]; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_FLOAT: return a.valueFloat == b.valueFloat; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_DOUBLE: @@ -507,6 +507,7 @@ static id BoxedValue(CGPValue value, CGPFieldJavaType type) { case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BOOLEAN: return JavaLangBoolean_valueOfWithBoolean_(value.valueBool); case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: + return value.valueEnum->enum_; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: @@ -533,6 +534,8 @@ static CGPValue UnboxValue(id value, CGPFieldJavaType type) { result.valueBool = [value booleanValue]; break; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM: + result.valueEnum = [value getValueDescriptor]; + break; case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_BYTE_STRING: case ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_MESSAGE: @@ -546,8 +549,7 @@ static CGPValue UnboxValue(id value, CGPFieldJavaType type) { // java.lang.Integer using the enum number (not ordinal). static id BoxedReflectionValue(CGPValue value, CGPFieldJavaType type) { if (type == ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_ENUM) { - return JavaLangInteger_valueOfWithInt_( - [(id)value.valueId getNumber]); + return JavaLangInteger_valueOfWithInt_([value.valueEnum getNumber]); } return BoxedValue(value, type); } @@ -558,7 +560,7 @@ static CGPValue UnboxReflectionValue(id value, CGPFieldDescriptor *field) { CGPEnumValueDescriptor *valueDesc = CGPEnumValueDescriptorFromInt(field->valueType_, [value intValue]); CGPValue result; - result.valueId = valueDesc ? valueDesc->enum_ : nil; + result.valueEnum = valueDesc; return result; } return UnboxValue(value, type); diff --git a/protobuf/runtime/src/com/google/protobuf/RepeatedField.h b/protobuf/runtime/src/com/google/protobuf/RepeatedField.h index ab11be09d9..b9fcf5c171 100644 --- a/protobuf/runtime/src/com/google/protobuf/RepeatedField.h +++ b/protobuf/runtime/src/com/google/protobuf/RepeatedField.h @@ -90,14 +90,6 @@ CGP_ALWAYS_INLINE void CGPRepeatedFieldCheckBounds(CGPRepeatedField *field, jint } } -CGP_ALWAYS_INLINE void CGPRepeatedFieldAddRetainedId(CGPRepeatedField *field, id value) { - uint32_t total_size = CGPRepeatedFieldTotalSize(field); - if (CGPRepeatedFieldSize(field) == total_size) { - CGPRepeatedFieldReserve(field, total_size + 1, sizeof(id)); - } - ((void **)field->data->buffer)[field->data->size++] = (ARCBRIDGE void *)(value); -} - id CGPNewRepeatedFieldList(CGPRepeatedField *field, CGPFieldJavaType type); NSArray *CGPNewRepeatedFieldArray(CGPRepeatedField *field, CGPFieldJavaType type); diff --git a/protobuf/runtime/src/com/google/protobuf/RepeatedField.m b/protobuf/runtime/src/com/google/protobuf/RepeatedField.m index 90a090af6d..cce9e3fffd 100644 --- a/protobuf/runtime/src/com/google/protobuf/RepeatedField.m +++ b/protobuf/runtime/src/com/google/protobuf/RepeatedField.m @@ -58,8 +58,10 @@ void CGPRepeatedFieldReserve(CGPRepeatedField *field, uint32_t new_size, size_t } uint32_t newTotalSize = MAX(MIN_REPEATED_FIELD_SIZE, MAX(data->total_size * 2, new_size)); + uint32_t oldTotalSize = data->total_size; data->total_size = newTotalSize; data->buffer = realloc(data->buffer, newTotalSize * elemSize); + bzero(data->buffer + elemSize * oldTotalSize, elemSize * (newTotalSize - oldTotalSize)); } void CGPRepeatedFieldCopyData(CGPRepeatedField *field, CGPFieldJavaType type) { @@ -82,8 +84,8 @@ void CGPRepeatedFieldCopyData(CGPRepeatedField *field, CGPFieldJavaType type) { } } -void CGPRepeatedFieldAppendOther( - CGPRepeatedField *field, CGPRepeatedField *other, CGPFieldJavaType type) { +void CGPRepeatedFieldAppendOther(CGPRepeatedField *field, CGPRepeatedField *other, + CGPFieldJavaType type) { uint32_t otherSize = CGPRepeatedFieldSize(other); if (otherSize == 0) { return; @@ -130,9 +132,9 @@ id CGPRepeatedFieldGet(CGPRepeatedField *field, jint index, CGPFieldDescriptor * CGPRepeatedFieldCheckBounds(field, index); #define REPEATED_GET_CASE(NAME) \ - return CGPToReflectionType##NAME(((TYPE_##NAME *)field->data->buffer)[index], descriptor); \ + return CGPToReflectionType##NAME(((TYPE_##NAME *)field->data->buffer)[index]); - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(descriptor), REPEATED_GET_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(descriptor), REPEATED_GET_CASE) #undef REPEATED_GET_CASE } @@ -143,9 +145,7 @@ void CGPRepeatedMessageFieldRemove(CGPRepeatedField *field, jint index) { id *msgBuffer = (id *)field->data->buffer; AUTORELEASE(msgBuffer[index]); if (count > (uint32_t)index + 1) { - memmove(&(msgBuffer[index]), - &(msgBuffer[index + 1]), - sizeof(id) * (count - (index + 1))); + memmove(&(msgBuffer[index]), &(msgBuffer[index + 1]), sizeof(id) * (count - (index + 1))); } field->data->size -= 1; } @@ -153,26 +153,26 @@ void CGPRepeatedMessageFieldRemove(CGPRepeatedField *field, jint index) { void CGPRepeatedFieldSet(CGPRepeatedField *field, jint index, id value, CGPFieldJavaType type) { CGPRepeatedFieldCheckBounds(field, index); -#define REPEATED_SET_CASE(NAME) \ - { \ +#define REPEATED_SET_CASE(NAME) \ + { \ TYPE_##NAME *ptr = &((TYPE_##NAME *)field->data->buffer)[index]; \ - TYPE_ASSIGN_##NAME(*ptr, CGPFromReflectionType##NAME(value)); \ - break; \ + TYPE_ASSIGN_##NAME(ptr, CGPFromReflectionType##NAME(value)); \ } - SWITCH_TYPES_WITH_ENUM(type, REPEATED_SET_CASE) + SWITCH_TYPES(type, REPEATED_SET_CASE) #undef REPEATED_SET_CASE } // Make sure to reserve enough space in the buffer BEFORE calling this. static void CGPRepeatedFieldAddUnsafe(CGPRepeatedFieldData *data, id value, CGPFieldJavaType type) { -#define REPEATED_ADD_CASE(NAME) \ - ((TYPE_##NAME *)data->buffer)[data->size++] = \ - TYPE_RETAIN_##NAME(CGPFromReflectionType##NAME(value)); \ - break; +#define REPEATED_ADD_CASE(NAME) \ + { \ + TYPE_##NAME *ptr = &((TYPE_##NAME *)data->buffer)[data->size++]; \ + TYPE_ASSIGN_##NAME(ptr, CGPFromReflectionType##NAME(value)); \ + } - SWITCH_TYPES_WITH_ENUM(type, REPEATED_ADD_CASE) + SWITCH_TYPES(type, REPEATED_ADD_CASE) #undef REPEATED_ADD_CASE } @@ -185,8 +185,8 @@ void CGPRepeatedFieldAdd(CGPRepeatedField *field, id value, CGPFieldJavaType typ CGPRepeatedFieldAddUnsafe(field->data, value, type); } -void CGPRepeatedFieldAssignFromList( - CGPRepeatedField *field, id list, CGPFieldJavaType type) { +void CGPRepeatedFieldAssignFromList(CGPRepeatedField *field, id list, + CGPFieldJavaType type) { CGPRepeatedFieldClear(field, type); CGPRepeatedFieldReserve(field, [list size], CGPGetTypeSize(type)); @@ -203,13 +203,12 @@ void CGPRepeatedFieldAssignFromList( return newList; } -#define REPEATED_COPY_ELEM_CASE(NAME) \ - for (uint32_t i = 0; i < data->size; i++) { \ - [newList addWithId:CGPToReflectionType##NAME(((TYPE_##NAME *)data->buffer)[i], descriptor)]; \ - } \ - break; +#define REPEATED_COPY_ELEM_CASE(NAME) \ + for (uint32_t i = 0; i < data->size; i++) { \ + [newList addWithId:CGPToReflectionType##NAME(((TYPE_##NAME *)data->buffer)[i])]; \ + } - SWITCH_TYPES_WITH_ENUM(CGPFieldGetJavaType(descriptor), REPEATED_COPY_ELEM_CASE) + SWITCH_TYPES(CGPFieldGetJavaType(descriptor), REPEATED_COPY_ELEM_CASE) #undef REPEATED_COPY_ELEM_CASE @@ -254,7 +253,7 @@ @interface CGPRepeatedFieldList : JavaUtilAbstractList { @end // We need a subclass for String fields which must implement the ProtocolStringList interface. -@interface CGPRepeatedStringFieldList : CGPRepeatedFieldList < ComGoogleProtobufProtocolStringList > +@interface CGPRepeatedStringFieldList : CGPRepeatedFieldList @end @interface CGPStringAsByteStringList : JavaUtilAbstractList { @@ -265,8 +264,9 @@ @interface CGPStringAsByteStringList : JavaUtilAbstractList { id CGPNewRepeatedFieldList(CGPRepeatedField *field, CGPFieldJavaType type) { CGPRepeatedFieldList *list = - type == ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING ? - [[CGPRepeatedStringFieldList alloc] init] : [[CGPRepeatedFieldList alloc] init]; + type == ComGoogleProtobufDescriptors_FieldDescriptor_JavaType_Enum_STRING + ? [[CGPRepeatedStringFieldList alloc] init] + : [[CGPRepeatedFieldList alloc] init]; CGPRepeatedFieldData *data = field->data; if (data != NULL) { list->field_.data = data; @@ -293,9 +293,9 @@ - (id)getWithInt:(jint)index { CGPRepeatedFieldCheckBounds(&field_, index); #define REPEATED_LIST_GET_CASE(NAME) \ - return CGPBoxedValue##NAME(((TYPE_##NAME *)field_.data->buffer)[index]); \ + return CGPBoxedValue##NAME(((TYPE_##NAME *)field_.data->buffer)[index]); - SWITCH_TYPES_NO_ENUM(type_, REPEATED_LIST_GET_CASE) + SWITCH_TYPES(type_, REPEATED_LIST_GET_CASE) #undef REPEATED_LIST_GET_CASE } diff --git a/protobuf/tests/Proto3EnumTest.java b/protobuf/tests/Proto3EnumTest.java index acae257070..26341a6177 100644 --- a/protobuf/tests/Proto3EnumTest.java +++ b/protobuf/tests/Proto3EnumTest.java @@ -101,4 +101,41 @@ public void testNegativeEnumNumber() throws Exception { Text text = Text.parseFrom(new byte[] {0x08, 0x7f}, ExtensionRegistry.getEmptyRegistry()); assertThat(text.getGreeting()).isSameInstanceAs(Greetings.UNRECOGNIZED); } + + public void testSingularParseUnknownEnumSerialization() throws Exception { + // field 1 (fruit), value 5 (unrecognized) + // Tag: (1 << 3) | 0 = 8 + // Value: 5 + byte[] bytes = new byte[] {0x08, 0x05}; + FruitBox box = FruitBox.parseFrom(bytes, ExtensionRegistry.getEmptyRegistry()); + + byte[] outputBytes = box.toByteArray(); + assertThat(outputBytes).isEqualTo(bytes); + } + + public void testRepeatedParseUnknownEnumSerialization() throws Exception { + // field 2 (fruits), repeated, packed + // Tag: (2 << 3) | 2 = 18 + // Length: 3 + // Values: 1 (APPLE), 2 (BANANA), 5 (unrecognized) + byte[] bytes = new byte[] {0x12, 0x03, 0x01, 0x02, 0x05}; + FruitBox box = FruitBox.parseFrom(bytes, ExtensionRegistry.getEmptyRegistry()); + + byte[] outputBytes = box.toByteArray(); + assertThat(outputBytes).isEqualTo(bytes); + } + + public void testMapParseUnknownEnumSerialization() throws Exception { + // field 3 (fruit_map), map + // Tag: (3 << 3) | 2 = 26 + // Length: 4 + // Map Entry: + // key: field 1, value 1 -> 0x08 0x01 + // value: field 2, value 5 -> 0x10 0x05 + byte[] bytes = new byte[] {0x1a, 0x04, 0x08, 0x01, 0x10, 0x05}; + FruitBox box = FruitBox.parseFrom(bytes, ExtensionRegistry.getEmptyRegistry()); + + byte[] outputBytes = box.toByteArray(); + assertThat(outputBytes).isEqualTo(bytes); + } } diff --git a/protobuf/tests/protos/proto3_enum.proto b/protobuf/tests/protos/proto3_enum.proto index 663c761f72..12a1f1d542 100644 --- a/protobuf/tests/protos/proto3_enum.proto +++ b/protobuf/tests/protos/proto3_enum.proto @@ -27,6 +27,8 @@ enum Fruit { message FruitBox { Fruit fruit = 1; + repeated Fruit fruits = 2; + map fruit_map = 3; } enum Greetings {