diff options
90 files changed, 1656 insertions, 397 deletions
diff --git a/Makefile.am b/Makefile.am index 41d25823..a4de1bd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -534,6 +534,7 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBTestUtilities.h \ objectivec/Tests/GPBTestUtilities.m \ objectivec/Tests/GPBUnittestProtos.m \ + objectivec/Tests/GPBUnittestProtos2.m \ objectivec/Tests/GPBUnknownFieldSetTest.m \ objectivec/Tests/GPBUtilitiesTests.m \ objectivec/Tests/GPBWellKnownTypesTest.m \ @@ -555,6 +556,13 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/text_format_map_unittest_data.txt \ objectivec/Tests/text_format_unittest_data.txt \ objectivec/Tests/unittest_cycle.proto \ + objectivec/Tests/unittest_extension_chain_a.proto \ + objectivec/Tests/unittest_extension_chain_b.proto \ + objectivec/Tests/unittest_extension_chain_c.proto \ + objectivec/Tests/unittest_extension_chain_d.proto \ + objectivec/Tests/unittest_extension_chain_e.proto \ + objectivec/Tests/unittest_extension_chain_f.proto \ + objectivec/Tests/unittest_extension_chain_g.proto \ objectivec/Tests/unittest_objc.proto \ objectivec/Tests/unittest_objc_startup.proto \ objectivec/Tests/unittest_runtime_proto2.proto \ @@ -1,15 +1,15 @@ -new_http_archive( - name = "gmock_archive", - url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip", - sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b", +new_git_repository( + name = "googletest", build_file = "gmock.BUILD", + remote = "https://github.com/google/googletest", + tag = "release-1.8.0", ) new_http_archive( name = "six_archive", - url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55", - sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", build_file = "six.BUILD", + sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a", + url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55", ) bind( @@ -19,12 +19,12 @@ bind( bind( name = "gtest", - actual = "@gmock_archive//:gtest", + actual = "@googletest//:gtest", ) bind( name = "gtest_main", - actual = "@gmock_archive//:gtest_main", + actual = "@googletest//:gtest_main", ) bind( @@ -33,8 +33,8 @@ bind( ) maven_jar( - name = "guava_maven", - artifact = "com.google.guava:guava:18.0", + name = "guava_maven", + artifact = "com.google.guava:guava:18.0", ) bind( @@ -43,8 +43,8 @@ bind( ) maven_jar( - name = "gson_maven", - artifact = "com.google.code.gson:gson:2.3", + name = "gson_maven", + artifact = "com.google.code.gson:gson:2.3", ) bind( diff --git a/appveyor.bat b/appveyor.bat index 0e6dd520..916f4434 100644 --- a/appveyor.bat +++ b/appveyor.bat @@ -10,7 +10,7 @@ goto :error echo Building C++ mkdir build_msvc cd build_msvc -cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% ../cmake +cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% ../cmake msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error cd %configuration% tests.exe || goto error diff --git a/appveyor.yml b/appveyor.yml index 2ea3cb78..20fc8ade 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,7 @@ environment: matrix: - language: cpp BUILD_DLL: ON + UNICODE: ON - language: csharp diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index f947b741..df3b2012 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -159,6 +159,10 @@ else (MSVC) set(LIB_PREFIX) endif (MSVC) +if (protobuf_UNICODE) + add_definitions(-DUNICODE -D_UNICODE) +endif (protobuf_UNICODE) + include(libprotobuf-lite.cmake) include(libprotobuf.cmake) include(libprotoc.cmake) diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index ab7cd922..94efea9e 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -251,17 +251,6 @@ namespace Google.Protobuf.Reflection "Dependencies passed to FileDescriptor.BuildFrom() don't match " + "those listed in the FileDescriptorProto."); } - for (int i = 0; i < proto.Dependency.Count; i++) - { - if (dependencies[i].Name != proto.Dependency[i]) - { - throw new DescriptorValidationException( - result, - "Dependencies passed to FileDescriptor.BuildFrom() don't match " + - "those listed in the FileDescriptorProto. Expected: " + - proto.Dependency[i] + " but was: " + dependencies[i].Name); - } - } result.CrossLink(); return result; @@ -341,4 +330,4 @@ namespace Google.Protobuf.Reflection /// </value> public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } } } -}
\ No newline at end of file +} diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh index c170c837..668e6d13 100755 --- a/generate_descriptor_proto.sh +++ b/generate_descriptor_proto.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Run this script to regenerate descriptor.pb.{h,cc} after the protocol # compiler changes. Since these files are compiled into the protocol compiler diff --git a/gmock.BUILD b/gmock.BUILD index 82abf275..b1ae15a9 100644 --- a/gmock.BUILD +++ b/gmock.BUILD @@ -1,19 +1,19 @@ cc_library( name = "gtest", srcs = [ - "gmock-1.7.0/gtest/src/gtest-all.cc", - "gmock-1.7.0/src/gmock-all.cc", + "googletest/src/gtest-all.cc", + "googlemock/src/gmock-all.cc", ], hdrs = glob([ - "gmock-1.7.0/**/*.h", - "gmock-1.7.0/gtest/src/*.cc", - "gmock-1.7.0/src/*.cc", + "**/*.h", + "googletest/src/*.cc", + "googlemock/src/*.cc", ]), includes = [ - "gmock-1.7.0", - "gmock-1.7.0/gtest", - "gmock-1.7.0/gtest/include", - "gmock-1.7.0/include", + "googlemock", + "googletest", + "googletest/include", + "googlemock/include", ], linkopts = ["-pthread"], visibility = ["//visibility:public"], @@ -21,7 +21,7 @@ cc_library( cc_library( name = "gtest_main", - srcs = ["gmock-1.7.0/src/gmock_main.cc"], + srcs = ["googlemock/src/gmock_main.cc"], linkopts = ["-pthread"], visibility = ["//visibility:public"], deps = [":gtest"], diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index ad50cc0e..d4db9c80 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -224,7 +224,7 @@ public class JsonFormat { * Creates a {@link Parser} with default configuration. */ public static Parser parser() { - return new Parser(TypeRegistry.getEmptyTypeRegistry()); + return new Parser(TypeRegistry.getEmptyTypeRegistry(), false); } /** @@ -232,9 +232,11 @@ public class JsonFormat { */ public static class Parser { private final TypeRegistry registry; + private final boolean ignoringUnknownFields; - private Parser(TypeRegistry registry) { + private Parser(TypeRegistry registry, boolean ignoreUnknownFields) { this.registry = registry; + this.ignoringUnknownFields = ignoreUnknownFields; } /** @@ -247,7 +249,16 @@ public class JsonFormat { if (this.registry != TypeRegistry.getEmptyTypeRegistry()) { throw new IllegalArgumentException("Only one registry is allowed."); } - return new Parser(registry); + return new Parser(registry, this.ignoringUnknownFields); + } + + /** + * Creates a new {@link Parser} configured to not throw an exception + * when an unknown field is encountered. The new Parser clones all other + * configurations from this Parser. + */ + public Parser ignoringUnknownFields() { + return new Parser(this.registry, true); } /** @@ -259,7 +270,7 @@ public class JsonFormat { public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException { // TODO(xiaofeng): Investigate the allocation overhead and optimize for // mobile. - new ParserImpl(registry).merge(json, builder); + new ParserImpl(registry, ignoringUnknownFields).merge(json, builder); } /** @@ -272,7 +283,7 @@ public class JsonFormat { public void merge(Reader json, Message.Builder builder) throws IOException { // TODO(xiaofeng): Investigate the allocation overhead and optimize for // mobile. - new ParserImpl(registry).merge(json, builder); + new ParserImpl(registry, ignoringUnknownFields).merge(json, builder); } } @@ -1024,9 +1035,11 @@ public class JsonFormat { private static class ParserImpl { private final TypeRegistry registry; private final JsonParser jsonParser; + private final boolean ignoringUnknownFields; - ParserImpl(TypeRegistry registry) { + ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields) { this.registry = registry; + this.ignoringUnknownFields = ignoreUnknownFields; this.jsonParser = new JsonParser(); } @@ -1191,6 +1204,9 @@ public class JsonFormat { } FieldDescriptor field = fieldNameMap.get(entry.getKey()); if (field == null) { + if (ignoringUnknownFields) { + continue; + } throw new InvalidProtocolBufferException( "Cannot find field: " + entry.getKey() diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java index 6fc784ef..c11114c0 100644 --- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java @@ -1030,6 +1030,22 @@ public class JsonFormatTest extends TestCase { } } + public void testParserUnknownFields() throws Exception { + try { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}"; + JsonFormat.parser().merge(json, builder); + fail("Exception is expected."); + } catch (InvalidProtocolBufferException e) { + // Expected. + } + } + public void testParserIgnoringUnknownFields() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}"; + JsonFormat.parser().ignoringUnknownFields().merge(json, builder); + } + public void testCustomJsonName() throws Exception { TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build(); assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message)); diff --git a/javanano/pom.xml b/javanano/pom.xml index e6a03d15..6ebba3cf 100644 --- a/javanano/pom.xml +++ b/javanano/pom.xml @@ -164,8 +164,8 @@ <configuration> <instructions> <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL> - <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName> - <Export-Package>com.google.protobuf;version=3.0.0-alpha-7</Export-Package> + <Bundle-SymbolicName>com.google.protobuf.nano</Bundle-SymbolicName> + <Export-Package>com.google.protobuf.nano;version=3.0.0-alpha-7</Export-Package> </instructions> </configuration> </plugin> diff --git a/js/commonjs/export.js b/js/commonjs/export.js index fb56b30b..2403b1a4 100644 --- a/js/commonjs/export.js +++ b/js/commonjs/export.js @@ -11,7 +11,9 @@ goog.require('jspb.BinaryWriter'); goog.require('jspb.ExtensionFieldBinaryInfo'); goog.require('jspb.ExtensionFieldInfo'); goog.require('jspb.Message'); +goog.require('jspb.Map'); +exports.Map = jspb.Map; exports.Message = jspb.Message; exports.BinaryReader = jspb.BinaryReader; exports.BinaryWriter = jspb.BinaryWriter; diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh index 82953130..6cc32da9 100755 --- a/objectivec/DevTools/compile_testing_protos.sh +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -1,17 +1,16 @@ -#!/bin/bash - +#!/bin/bash -eu # Invoked by the Xcode projects to build the protos needed for the unittests. -set -eu - readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos" +# ----------------------------------------------------------------------------- # Helper for bailing. die() { echo "Error: $1" exit 2 } +# ----------------------------------------------------------------------------- # What to do. case "${ACTION}" in "") @@ -26,12 +25,19 @@ case "${ACTION}" in ;; esac -# Move to the top of the protobuf directories. -cd "${SRCROOT}/.." +# ----------------------------------------------------------------------------- +# Ensure the output dir exists +mkdir -p "${OUTPUT_DIR}/google/protobuf" +# ----------------------------------------------------------------------------- +# Move to the top of the protobuf directories and ensure there is a protoc +# binary to use. +cd "${SRCROOT}/.." [[ -x src/protoc ]] || \ die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)." +# ----------------------------------------------------------------------------- +# See the compiler or proto files have changed. RUN_PROTOC=no if [[ ! -d "${OUTPUT_DIR}" ]] ; then RUN_PROTOC=yes @@ -50,7 +56,7 @@ else # Find the oldest output file. readonly OldestOutput=$(find \ "${OUTPUT_DIR}" \ - -type f -print0 \ + -type f -name "*pbobjc.[hm]" -print0 \ | xargs -0 stat -f "%m %N" \ | sort -n -r | tail -n1 | cut -f2- -d" ") # If the newest input is newer than the oldest output, regenerate. @@ -64,10 +70,30 @@ if [[ "${RUN_PROTOC}" != "yes" ]] ; then exit 0 fi -# Ensure the output dir exists -mkdir -p "${OUTPUT_DIR}/google/protobuf" +# ----------------------------------------------------------------------------- +# Prune out all the files from previous generations to ensure we only have +# current ones. +find "${OUTPUT_DIR}" \ + -type f -name "*pbobjc.[hm]" -print0 \ + | xargs -0 rm -rf + +# ----------------------------------------------------------------------------- +# Helper to invoke protoc +compile_protos() { + src/protoc \ + --objc_out="${OUTPUT_DIR}/google/protobuf" \ + --proto_path=src/google/protobuf/ \ + --proto_path=src \ + "$@" +} + +# ----------------------------------------------------------------------------- +# Generate most of the proto files that exist in the C++ src tree. Several +# are used in the tests, but the extra don't hurt in that they ensure ObjC +# sources can be generated from them. CORE_PROTO_FILES=( + src/google/protobuf/any_test.proto src/google/protobuf/unittest_arena.proto src/google/protobuf/unittest_custom_options.proto src/google/protobuf/unittest_enormous_descriptor.proto @@ -90,35 +116,32 @@ CORE_PROTO_FILES=( src/google/protobuf/map_lite_unittest.proto src/google/protobuf/map_proto2_unittest.proto src/google/protobuf/map_unittest.proto -) - -# The unittest_custom_options.proto extends the messages in descriptor.proto -# so we build it in to test extending in general. The library doesn't provide -# a descriptor as it doesn't use the classes/enums. -CORE_PROTO_FILES+=( + # The unittest_custom_options.proto extends the messages in descriptor.proto + # so we build it in to test extending in general. The library doesn't provide + # a descriptor as it doesn't use the classes/enums. src/google/protobuf/descriptor.proto ) -compile_proto() { - src/protoc \ - --objc_out="${OUTPUT_DIR}/google/protobuf" \ - --proto_path=src/google/protobuf/ \ - --proto_path=src \ - $* -} - +# Note: there is overlap in package.Message names between some of the test +# files, so they can't be generated all at once. This works because the overlap +# isn't linked into a single binary. for a_proto in "${CORE_PROTO_FILES[@]}" ; do - compile_proto "${a_proto}" + compile_protos "${a_proto}" done -OBJC_PROTO_FILES=( - objectivec/Tests/unittest_cycle.proto - objectivec/Tests/unittest_runtime_proto2.proto - objectivec/Tests/unittest_runtime_proto3.proto - objectivec/Tests/unittest_objc.proto +# ----------------------------------------------------------------------------- +# Generate the Objective C specific testing protos. +compile_protos \ + --proto_path="objectivec/Tests" \ + objectivec/Tests/unittest_cycle.proto \ + objectivec/Tests/unittest_extension_chain_a.proto \ + objectivec/Tests/unittest_extension_chain_b.proto \ + objectivec/Tests/unittest_extension_chain_c.proto \ + objectivec/Tests/unittest_extension_chain_d.proto \ + objectivec/Tests/unittest_extension_chain_e.proto \ + objectivec/Tests/unittest_extension_chain_f.proto \ + objectivec/Tests/unittest_extension_chain_g.proto \ + objectivec/Tests/unittest_runtime_proto2.proto \ + objectivec/Tests/unittest_runtime_proto3.proto \ + objectivec/Tests/unittest_objc.proto \ objectivec/Tests/unittest_objc_startup.proto -) - -for a_proto in "${OBJC_PROTO_FILES[@]}" ; do - compile_proto --proto_path="objectivec/Tests" "${a_proto}" -done diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m index 64869bbb..ae57747d 100644 --- a/objectivec/GPBArray.m +++ b/objectivec/GPBArray.m @@ -195,7 +195,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //%} //% //%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block { -//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:0 usingBlock:block]; +//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; //%} //% //%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts @@ -406,7 +406,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -654,7 +654,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -902,7 +902,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -1150,7 +1150,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -1398,7 +1398,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -1646,7 +1646,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -1894,7 +1894,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts @@ -2166,7 +2166,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateRawValuesWithOptions:0 usingBlock:block]; + [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts @@ -2218,7 +2218,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block { - [self enumerateValuesWithOptions:0 usingBlock:block]; + [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block]; } - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index 2e5bdc71..7dc943d4 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -99,4 +99,4 @@ // regenerated. // // Meant to be used internally by generated code. -#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 +#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30002 diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index 251a159c..7c3ab447 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -290,7 +290,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, maxLength:bufferBytesLeft usedLength:&usedBufferLength encoding:NSUTF8StringEncoding - options:0 + options:(NSStringEncodingConversionOptions)0 range:NSMakeRange(0, [value length]) remainingRange:NULL]; } diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 36fb4eae..651f4de0 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -81,6 +81,13 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { @property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat; /** The class of this message. */ @property(nonatomic, readonly) Class messageClass; +/** Containing message descriptor if this message is nested, or nil otherwise. */ +@property(readonly, nullable) GPBDescriptor *containingType; +/** + * Fully qualified name for this message (package.message). Can be nil if the + * value is unable to be computed. + */ +@property(readonly, nullable) NSString *fullName; /** * Gets the field for the given number. @@ -118,6 +125,8 @@ typedef NS_ENUM(uint8_t, GPBFieldType) { /** The package declared in the proto file. */ @property(nonatomic, readonly, copy) NSString *package; +/** The objc prefix declared in the proto file. */ +@property(nonatomic, readonly, copy, nullable) NSString *objcPrefix; /** The syntax of the proto file. */ @property(nonatomic, readonly) GPBFileSyntax syntax; diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index dccb9bc8..0753a948 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -42,8 +42,10 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdirect-ivar-access" -// The address of this variable is used as a key for obj_getAssociatedObject. +// The addresses of these variables are used as keys for objc_getAssociatedObject. static const char kTextFormatExtraValueKey = 0; +static const char kParentClassNameValueKey = 0; +static const char kClassNameSuffixKey = 0; // Utility function to generate selectors on the fly. static SEL SelFromStrings(const char *prefix, const char *middle, @@ -215,10 +217,102 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, extensionRangesCount_ = count; } +- (void)setupContainingMessageClassName:(const char *)msgClassName { + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). + NSAssert(objc_getClass(msgClassName), @"Class %s not defined", msgClassName); + NSValue *parentNameValue = [NSValue valueWithPointer:msgClassName]; + objc_setAssociatedObject(self, &kParentClassNameValueKey, + parentNameValue, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)setupMessageClassNameSuffix:(NSString *)suffix { + if (suffix.length) { + objc_setAssociatedObject(self, &kClassNameSuffixKey, + suffix, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } +} + - (NSString *)name { return NSStringFromClass(messageClass_); } +- (GPBDescriptor *)containingType { + NSValue *parentNameValue = + objc_getAssociatedObject(self, &kParentClassNameValueKey); + if (!parentNameValue) { + return nil; + } + const char *parentName = [parentNameValue pointerValue]; + Class parentClass = objc_getClass(parentName); + NSAssert(parentClass, @"Class %s not defined", parentName); + return [parentClass descriptor]; +} + +- (NSString *)fullName { + NSString *className = NSStringFromClass(self.messageClass); + GPBFileDescriptor *file = self.file; + NSString *objcPrefix = file.objcPrefix; + if (objcPrefix && ![className hasPrefix:objcPrefix]) { + NSAssert(0, + @"Class didn't have correct prefix? (%@ - %@)", + className, objcPrefix); + return nil; + } + GPBDescriptor *parent = self.containingType; + + NSString *name = nil; + if (parent) { + NSString *parentClassName = NSStringFromClass(parent.messageClass); + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); + if (suffix) { + if (![parentClassName hasSuffix:suffix]) { + NSAssert(0, + @"ParentMessage class didn't have correct suffix? (%@ - %@)", + className, suffix); + return nil; + } + parentClassName = + [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; + } + NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; + if (![className hasPrefix:parentPrefix]) { + NSAssert(0, + @"Class didn't have the correct parent name prefix? (%@ - %@)", + parentPrefix, className); + return nil; + } + name = [className substringFromIndex:parentPrefix.length]; + } else { + name = [className substringFromIndex:objcPrefix.length]; + } + + // The generator will add _Class to avoid reserved words, drop it. + NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); + if (suffix) { + if (![name hasSuffix:suffix]) { + NSAssert(0, + @"Message class didn't have correct suffix? (%@ - %@)", + name, suffix); + return nil; + } + name = [name substringToIndex:(name.length - suffix.length)]; + } + + NSString *prefix = (parent != nil ? parent.fullName : file.package); + NSString *result; + if (prefix.length > 0) { + result = [NSString stringWithFormat:@"%@.%@", prefix, name]; + } else { + result = name; + } + return result; +} + - (id)copyWithZone:(NSZone *)zone { #pragma unused(zone) return [self retain]; @@ -255,13 +349,27 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, @implementation GPBFileDescriptor { NSString *package_; + NSString *objcPrefix_; GPBFileSyntax syntax_; } @synthesize package = package_; +@synthesize objcPrefix = objcPrefix_; @synthesize syntax = syntax_; - (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax { + self = [super init]; + if (self) { + package_ = [package copy]; + objcPrefix_ = [objcPrefix copy]; + syntax_ = syntax; + } + return self; +} + +- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax { self = [super init]; if (self) { @@ -273,6 +381,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, - (void)dealloc { [package_ release]; + [objcPrefix_ release]; [super dealloc]; } @@ -416,6 +525,9 @@ uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { // Extra type specific data. if (isMessage) { const char *className = coreDesc->dataTypeSpecific.className; + // Note: Only fetch the class here, can't send messages to it because + // that could cause cycles back to this class within +initialize if + // two messages have each other in fields (i.e. - they build a graph). msgClass_ = objc_getClass(className); NSAssert(msgClass_, @"Class %s not defined", className); } else if (dataType == GPBDataTypeEnum) { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index c20ff6b0..9173e7a2 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -37,6 +37,7 @@ // Describes attributes of the field. typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { + GPBFieldNone = 0, // These map to standard protobuf concepts. GPBFieldRequired = 1 << 0, GPBFieldRepeated = 1 << 1, @@ -111,6 +112,7 @@ typedef struct GPBMessageFieldDescriptionWithDefault { // Describes attributes of the extension. typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { + GPBExtensionNone = 0, // These map to standard protobuf concepts. GPBExtensionRepeated = 1 << 0, GPBExtensionPacked = 1 << 1, @@ -130,6 +132,7 @@ typedef struct GPBExtensionDescription { } GPBExtensionDescription; typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { + GPBDescriptorInitializationFlag_None = 0, GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, GPBDescriptorInitializationFlag_WireFormat = 1 << 1, }; @@ -165,11 +168,16 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { firstHasIndex:(int32_t)firstHasIndex; - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; +- (void)setupContainingMessageClassName:(const char *)msgClassName; +- (void)setupMessageClassNameSuffix:(NSString *)suffix; @end @interface GPBFileDescriptor () - (instancetype)initWithPackage:(NSString *)package + objcPrefix:(NSString *)objcPrefix + syntax:(GPBFileSyntax)syntax; +- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax; @end diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h index 96d51d9e..90d96c6f 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -37,15 +37,32 @@ #endif #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS + #import <Protobuf/Any.pbobjc.h> #import <Protobuf/Duration.pbobjc.h> #import <Protobuf/Timestamp.pbobjc.h> #else + #import "google/protobuf/Any.pbobjc.h" #import "google/protobuf/Duration.pbobjc.h" #import "google/protobuf/Timestamp.pbobjc.h" #endif NS_ASSUME_NONNULL_BEGIN +#pragma mark - Errors + +/** NSError domain used for errors. */ +extern NSString *const GPBWellKnownTypesErrorDomain; + +/** Error code for NSError with GPBWellKnownTypesErrorDomain. */ +typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) { + /** The type_url could not be computed for the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeFailedToComputeTypeURL = -100, + /** type_url in a Any doesn’t match that of the requested GPBMessage class. */ + GPBWellKnownTypesErrorCodeTypeURLMismatch = -101, +}; + +#pragma mark - GPBTimestamp + /** * Category for GPBTimestamp to work with standard Foundation time/date types. **/ @@ -54,7 +71,12 @@ NS_ASSUME_NONNULL_BEGIN /** The NSDate representation of this GPBTimestamp. */ @property(nonatomic, readwrite, strong) NSDate *date; -/** The NSTimeInterval representation of this GPBTimestamp. */ +/** + * The NSTimeInterval representation of this GPBTimestamp. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ @property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970; /** @@ -77,12 +99,19 @@ NS_ASSUME_NONNULL_BEGIN @end +#pragma mark - GPBDuration + /** * Category for GPBDuration to work with standard Foundation time type. **/ @interface GPBDuration (GBPWellKnownTypes) -/** The NSTimeInterval representation of this GPBTimestamp. */ +/** + * The NSTimeInterval representation of this GPBDuration. + * + * @note: Not all second/nanos combinations can be represented in a + * NSTimeInterval, so getting this could be a lossy transform. + **/ @property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970; /** @@ -90,10 +119,116 @@ NS_ASSUME_NONNULL_BEGIN * * @param timeIntervalSince1970 Time interval to configure the GPBDuration with. * - * @return A newly initialized GPBTimestamp. + * @return A newly initialized GPBDuration. **/ - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970; @end +#pragma mark - GPBAny + +/** + * Category for GPBAny to help work with the message within the object. + **/ +@interface GPBAny (GBPWellKnownTypes) + +/** + * Convenience method to create a GPBAny containing the serialized message. + * This uses type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Convenience method to create a GPBAny containing the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ ++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Initializes a GPBAny to contain the serialized message. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return A newly configured GPBAny with the given message, or nil on failure. + */ +- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. This uses + * type.googleapis.com/ as the type_url's prefix. + * + * @param message The message to be packed into the GPBAny. + * @param errorPtr Pointer to an error that will be populated if something goes + * wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + error:(NSError **)errorPtr; + +/** + * Packs the serialized message into this GPBAny. + * + * @param message The message to be packed into the GPBAny. + * @param typeURLPrefix The URL prefix to apply for type_url. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return Whether the packing was successful or not. + */ +- (BOOL)packWithMessage:(nonnull GPBMessage *)message + typeURLPrefix:(nonnull NSString *)typeURLPrefix + error:(NSError **)errorPtr; + +/** + * Unpacks the serialized message as if it was an instance of the given class. + * + * @note When checking type_url, the base URL is not checked, only the fully + * qualified name. + * + * @param messageClass The class to use to deserialize the contained message. + * @param errorPtr Pointer to an error that will be populated if something + * goes wrong. + * + * @return An instance of the given class populated with the contained data, or + * nil on failure. + */ +- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr; + +@end + NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m index 5cdd62d5..ed798a2e 100644 --- a/objectivec/GPBWellKnownTypes.m +++ b/objectivec/GPBWellKnownTypes.m @@ -34,6 +34,13 @@ #import "GPBWellKnownTypes.h" +#import "GPBUtilities_PackagePrivate.h" + +NSString *const GPBWellKnownTypesErrorDomain = + GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain); + +static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/"; + static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds, int32_t nanos) { return seconds + (NSTimeInterval)nanos / 1e9; @@ -48,6 +55,30 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, return (int32_t)nanos; } +static NSString *BuildTypeURL(NSString *typeURLPrefix, NSString *fullName) { + if (typeURLPrefix.length == 0) { + return fullName; + } + + if ([typeURLPrefix hasSuffix:@"/"]) { + return [typeURLPrefix stringByAppendingString:fullName]; + } + + return [NSString stringWithFormat:@"%@/%@", typeURLPrefix, fullName]; +} + +static NSString *ParseTypeFromURL(NSString *typeURLString) { + NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch]; + if ((range.location == NSNotFound) || + (NSMaxRange(range) == typeURLString.length)) { + return nil; + } + NSString *result = [typeURLString substringFromIndex:range.location + 1]; + return result; +} + +#pragma mark - GPBTimestamp + @implementation GPBTimestamp (GBPWellKnownTypes) - (instancetype)initWithDate:(NSDate *)date { @@ -87,6 +118,8 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, @end +#pragma mark - GPBDuration + @implementation GPBDuration (GBPWellKnownTypes) - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { @@ -113,3 +146,105 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, } @end + +#pragma mark - GPBAny + +@implementation GPBAny (GBPWellKnownTypes) + ++ (instancetype)anyWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self anyWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + ++ (instancetype)anyWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + return [[[self alloc] initWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr] autorelease]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self initWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (instancetype)initWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + self = [self init]; + if (self) { + if (![self packWithMessage:message + typeURLPrefix:typeURLPrefix + error:errorPtr]) { + [self release]; + self = nil; + } + } + return self; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + error:(NSError **)errorPtr { + return [self packWithMessage:message + typeURLPrefix:kTypePrefixGoogleApisCom + error:errorPtr]; +} + +- (BOOL)packWithMessage:(GPBMessage *)message + typeURLPrefix:(NSString *)typeURLPrefix + error:(NSError **)errorPtr { + NSString *fullName = [message descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return NO; + } + if (errorPtr) { + *errorPtr = nil; + } + self.typeURL = BuildTypeURL(typeURLPrefix, fullName); + self.value = message.data; + return YES; +} + +- (GPBMessage *)unpackMessageClass:(Class)messageClass + error:(NSError **)errorPtr { + NSString *fullName = [messageClass descriptor].fullName; + if (fullName.length == 0) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL + userInfo:nil]; + } + return nil; + } + + NSString *expectedFullName = ParseTypeFromURL(self.typeURL); + if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) { + if (errorPtr) { + *errorPtr = + [NSError errorWithDomain:GPBWellKnownTypesErrorDomain + code:GPBWellKnownTypesErrorCodeTypeURLMismatch + userInfo:nil]; + } + return nil; + } + + // Any is proto3, which means no extensions, so this assumes anything put + // within an any also won't need extensions. A second helper could be added + // if needed. + return [messageClass parseFromData:self.value + error:errorPtr]; +} + +@end diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 32067910..1585dbed 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -65,6 +65,7 @@ F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; + F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -211,6 +212,7 @@ F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; }; F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; }; F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; }; + F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -408,6 +410,7 @@ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */, 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, + F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */, 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */, @@ -659,6 +662,7 @@ F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */, 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */, F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */, 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, @@ -778,6 +782,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; @@ -838,6 +843,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 9f688f8d..b6bc95ab 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -73,6 +73,7 @@ F4E675D51B21D1620054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C21B21D1440054530B /* Struct.pbobjc.m */; }; F4E675D61B21D1620054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C51B21D1440054530B /* Type.pbobjc.m */; }; F4E675D71B21D1620054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675C71B21D1440054530B /* Wrappers.pbobjc.m */; }; + F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -234,6 +235,7 @@ F4E675DD1B21D1DE0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = "<group>"; }; F4E675DE1B21D1DE0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = "<group>"; }; F4E675DF1B21D1DE0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = "<group>"; }; + F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos2.m; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -446,6 +448,7 @@ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */, 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, + F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */, 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */, @@ -755,6 +758,7 @@ F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */, 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */, + F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */, F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, @@ -940,6 +944,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; @@ -1001,6 +1006,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_STATIC_ANALYZER_MODE = deep; + CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m index 74e3172b..1e1c3de8 100644 --- a/objectivec/Tests/GPBDescriptorTests.m +++ b/objectivec/Tests/GPBDescriptorTests.m @@ -34,12 +34,41 @@ #import "GPBDescriptor.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestObjc.pbobjc.h" +#import "google/protobuf/Descriptor.pbobjc.h" @interface DescriptorTests : GPBTestCase @end @implementation DescriptorTests +- (void)testDescriptor_containingType { + GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor]; + GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor]; + XCTAssertNil(testAllTypesDesc.containingType); + XCTAssertNotNil(nestedMessageDesc.containingType); + XCTAssertEqual(nestedMessageDesc.containingType, testAllTypesDesc); // Ptr comparison +} + +- (void)testDescriptor_fullName { + GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor]; + XCTAssertEqualObjects(testAllTypesDesc.fullName, @"protobuf_unittest.TestAllTypes"); + GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor]; + XCTAssertEqualObjects(nestedMessageDesc.fullName, @"protobuf_unittest.TestAllTypes.NestedMessage"); + + // Prefixes removed. + GPBDescriptor *descDesc = [GPBDescriptorProto descriptor]; + XCTAssertEqualObjects(descDesc.fullName, @"google.protobuf.DescriptorProto"); + GPBDescriptor *descExtRngDesc = [GPBDescriptorProto_ExtensionRange descriptor]; + XCTAssertEqualObjects(descExtRngDesc.fullName, @"google.protobuf.DescriptorProto.ExtensionRange"); + + // Things that get "_Class" added. + GPBDescriptor *pointDesc = [Point_Class descriptor]; + XCTAssertEqualObjects(pointDesc.fullName, @"protobuf_unittest.Point"); + GPBDescriptor *pointRectDesc = [Point_Rect descriptor]; + XCTAssertEqualObjects(pointRectDesc.fullName, @"protobuf_unittest.Point.Rect"); +} + - (void)testFieldDescriptor { GPBDescriptor *descriptor = [TestAllTypes descriptor]; diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 2cf9ccef..0058311b 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -36,6 +36,7 @@ #import "google/protobuf/MapUnittest.pbobjc.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestCycle.pbobjc.h" #import "google/protobuf/UnittestObjcStartup.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" @@ -49,11 +50,24 @@ // specific. - (void)testStartupOrdering { - // Just have to create a message. Nothing else uses the classes from - // this file, so the first selector invoked on the class will initialize - // it, which also initializes the root. + // Message class/Root class initialization is a little tricky, so these just + // create some possible patterns that can be a problem. The messages don't + // have to be exercised, just creating them is enough to test. If there + // is a problem, the runtime should assert or hang. + // + // Note: the messages from these proto files should not be used in any other + // tests, that way when they are referenced here it will be the first use and + // initialization will take place now. + TestObjCStartupMessage *message = [TestObjCStartupMessage message]; XCTAssertNotNil(message); + + CycleBaz *baz = [CycleBaz message]; + CycleBar *bar = [CycleBar message]; + CycleFoo *foo = [CycleFoo message]; + XCTAssertNotNil(baz); + XCTAssertNotNil(bar); + XCTAssertNotNil(foo); } - (void)testProto2HasMethodSupport { diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m index d19beee9..8d2948bf 100644 --- a/objectivec/Tests/GPBUnittestProtos.m +++ b/objectivec/Tests/GPBUnittestProtos.m @@ -36,6 +36,7 @@ // a descriptor as it doesn't use the classes/enums. #import "google/protobuf/Descriptor.pbobjc.m" +#import "google/protobuf/AnyTest.pbobjc.m" #import "google/protobuf/MapProto2Unittest.pbobjc.m" #import "google/protobuf/MapUnittest.pbobjc.m" #import "google/protobuf/Unittest.pbobjc.m" @@ -62,3 +63,11 @@ #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.m" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.m" + +#import "google/protobuf/UnittestExtensionChainA.pbobjc.m" +#import "google/protobuf/UnittestExtensionChainB.pbobjc.m" +#import "google/protobuf/UnittestExtensionChainC.pbobjc.m" +#import "google/protobuf/UnittestExtensionChainD.pbobjc.m" +#import "google/protobuf/UnittestExtensionChainE.pbobjc.m" +// See GPBUnittestProtos2.m for for "UnittestExtensionChainF.pbobjc.m" +#import "google/protobuf/UnittestExtensionChainG.pbobjc.m" diff --git a/objectivec/Tests/GPBUnittestProtos2.m b/objectivec/Tests/GPBUnittestProtos2.m new file mode 100644 index 00000000..ef9f0702 --- /dev/null +++ b/objectivec/Tests/GPBUnittestProtos2.m @@ -0,0 +1,34 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This one file in the chain tests is compiled by itself to ensure if was +// generated with the extra #imports needed to pull in the indirect Root class +// used in its Root registry. +#import "google/protobuf/UnittestExtensionChainF.pbobjc.m" diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m index 78f4e637..041841dd 100644 --- a/objectivec/Tests/GPBWellKnownTypesTest.m +++ b/objectivec/Tests/GPBWellKnownTypesTest.m @@ -32,6 +32,8 @@ #import <XCTest/XCTest.h> +#import "google/protobuf/AnyTest.pbobjc.h" + // A basically random interval into the future for testing with. static const NSTimeInterval kFutureOffsetInterval = 15000; @@ -99,4 +101,58 @@ static const NSTimeInterval kTimeAccuracy = 1e-9; [duration2 release]; } +- (void)testAnyHelpers { + + // Set and extract covers most of the code. + + TestAny *subMessage = [TestAny message]; + subMessage.int32Value = 12345; + TestAny *message = [TestAny message]; + NSError *err = nil; + message.anyValue = [GPBAny anyWithMessage:subMessage error:&err]; + XCTAssertNil(err); + + NSData *data = message.data; + XCTAssertNotNil(data); + + TestAny *message2 = [TestAny parseFromData:data error:&err]; + XCTAssertNil(err); + XCTAssertNotNil(message2); + XCTAssertTrue(message2.hasAnyValue); + + TestAny *subMessage2 = + (TestAny *)[message.anyValue unpackMessageClass:[TestAny class] + error:&err]; + XCTAssertNil(err); + XCTAssertNotNil(subMessage2); + XCTAssertEqual(subMessage2.int32Value, 12345); + + // NULL errorPtr in the two calls. + + message.anyValue = [GPBAny anyWithMessage:subMessage error:NULL]; + NSData *data2 = message.data; + XCTAssertEqualObjects(data2, data); + + TestAny *subMessage3 = + (TestAny *)[message.anyValue unpackMessageClass:[TestAny class] + error:NULL]; + XCTAssertNotNil(subMessage3); + XCTAssertEqualObjects(subMessage2, subMessage3); + + // Try to extract wrong type. + + GPBTimestamp *wrongMessage = + (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class] + error:&err]; + XCTAssertNotNil(err); + XCTAssertNil(wrongMessage); + XCTAssertEqualObjects(err.domain, GPBWellKnownTypesErrorDomain); + XCTAssertEqual(err.code, GPBWellKnownTypesErrorCodeTypeURLMismatch); + + wrongMessage = + (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class] + error:NULL]; + XCTAssertNil(wrongMessage); +} + @end diff --git a/objectivec/Tests/unittest_cycle.proto b/objectivec/Tests/unittest_cycle.proto index 5f6f56a1..afc1b0fe 100644 --- a/objectivec/Tests/unittest_cycle.proto +++ b/objectivec/Tests/unittest_cycle.proto @@ -31,10 +31,8 @@ syntax = "proto2"; package protobuf_unittest; -// Cycles in the Message graph can cause problems for the mutable classes -// since the properties on the mutable class change types. This file just -// needs to generate source, and that source must compile, to ensure the -// generated source works for this sort of case. +// Cycles in the Message graph can cause problems for message class +// initialization order. // You can't make a object graph that spans files, so this can only be done // within a single proto file. diff --git a/objectivec/Tests/unittest_extension_chain_a.proto b/objectivec/Tests/unittest_extension_chain_a.proto new file mode 100644 index 00000000..6a227eb9 --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_a.proto @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +import "unittest_extension_chain_b.proto"; +import "unittest_extension_chain_c.proto"; +import "unittest_extension_chain_d.proto"; + +// The Root for this file should end up adding the local extension and merging +// in the extensions from D's Root (unittest and C will come via D's). + +message ChainAMessage { + optional ChainBMessage b = 1; + optional ChainCMessage c = 2; + optional ChainDMessage d = 3; +} + +extend TestAllExtensions { + optional int32 chain_a_extension = 10001; +} diff --git a/objectivec/Tests/unittest_extension_chain_b.proto b/objectivec/Tests/unittest_extension_chain_b.proto new file mode 100644 index 00000000..0da7ed3e --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_b.proto @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +import "unittest_extension_chain_c.proto"; + +// The Root for this file should end up adding the local extension and merging +// in the extensions from C's Root (unittest will come via C's). + +message ChainBMessage { + optional ChainCMessage c = 1; +} + +extend TestAllExtensions { + optional int32 chain_b_extension = 10002; +} diff --git a/objectivec/Tests/unittest_extension_chain_c.proto b/objectivec/Tests/unittest_extension_chain_c.proto new file mode 100644 index 00000000..c702900a --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_c.proto @@ -0,0 +1,45 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +// The Root for this file should end up adding the local extension and merging +// in the extensions from unittest.proto's Root. + +message ChainCMessage { + optional int32 my_field = 1; +} + +extend TestAllExtensions { + optional int32 chain_c_extension = 10003; +} diff --git a/objectivec/Tests/unittest_extension_chain_d.proto b/objectivec/Tests/unittest_extension_chain_d.proto new file mode 100644 index 00000000..f9abe3ba --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_d.proto @@ -0,0 +1,49 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +import "unittest_extension_chain_b.proto"; +import "unittest_extension_chain_c.proto"; + +// The root should end up needing to merge B (C will be merged into B, so it +// doesn't need to be directly merged). + +message ChainDMessage { + optional ChainBMessage b = 1; + optional ChainCMessage c = 2; +} + +extend TestAllExtensions { + optional int32 chain_d_extension = 10004; +} diff --git a/objectivec/Tests/unittest_extension_chain_e.proto b/objectivec/Tests/unittest_extension_chain_e.proto new file mode 100644 index 00000000..fe116631 --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_e.proto @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "google/protobuf/unittest.proto"; + +// The Root for this file should end up just merging in unittest's Root. + +message ChainEMessage { + optional TestAllTypes my_field = 1; +} diff --git a/objectivec/Tests/unittest_extension_chain_f.proto b/objectivec/Tests/unittest_extension_chain_f.proto new file mode 100644 index 00000000..b9bed723 --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_f.proto @@ -0,0 +1,44 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "unittest_extension_chain_g.proto"; + +// The Root for this file should just be merging in the extensions from C's +// Root (because G doens't define anything itself). + +// The generated source will also have to directly import C's .h file so it can +// compile the reference to C's Root class. + +message ChainFMessage { + optional ChainGMessage g = 1; +} diff --git a/objectivec/Tests/unittest_extension_chain_g.proto b/objectivec/Tests/unittest_extension_chain_g.proto new file mode 100644 index 00000000..aee827b1 --- /dev/null +++ b/objectivec/Tests/unittest_extension_chain_g.proto @@ -0,0 +1,41 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2016 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +package protobuf_unittest; + +import "unittest_extension_chain_c.proto"; + +// The Root for this file should just be merging in the extensions from C's +// Root. + +message ChainGMessage { + optional ChainCMessage c = 1; +} diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h index 842052fe..b88b786a 100644 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index 25e5b4c4..e1054926 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBAnyRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBAnyRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -68,7 +72,7 @@ typedef struct GPBAny__storage_ { .number = GPBAny_FieldNumber_TypeURL, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBAny__storage_, typeURL), - .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), .dataType = GPBDataTypeString, }, { @@ -88,7 +92,7 @@ typedef struct GPBAny__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBAny__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index 182e866c..3750e093 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index cd37edaa..70437d49 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -31,18 +31,8 @@ @implementation GPBApiRoot -+ (GPBExtensionRegistry*)extensionRegistry { - // This is called by +initialize so there is no need to worry - // about thread safety and initialization of registry. - static GPBExtensionRegistry* registry = nil; - if (!registry) { - GPBDebugCheckRuntimeVersion(); - registry = [[GPBExtensionRegistry alloc] init]; - [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; - [registry addExtensions:[GPBTypeRoot extensionRegistry]]; - } - return registry; -} +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. @end @@ -55,6 +45,7 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -149,7 +140,7 @@ typedef struct GPBApi__storage_ { .number = GPBApi_FieldNumber_Syntax, .hasIndex = 3, .offset = (uint32_t)offsetof(GPBApi__storage_, syntax), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, }; @@ -160,7 +151,7 @@ typedef struct GPBApi__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBApi__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -223,7 +214,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_RequestTypeURL, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBMethod__storage_, requestTypeURL), - .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), .dataType = GPBDataTypeString, }, { @@ -241,7 +232,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_ResponseTypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBMethod__storage_, responseTypeURL), - .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), .dataType = GPBDataTypeString, }, { @@ -268,7 +259,7 @@ typedef struct GPBMethod__storage_ { .number = GPBMethod_FieldNumber_Syntax, .hasIndex = 7, .offset = (uint32_t)offsetof(GPBMethod__storage_, syntax), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, }; @@ -279,7 +270,7 @@ typedef struct GPBMethod__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMethod__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; @@ -350,7 +341,7 @@ typedef struct GPBMixin__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBMixin__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index fa91e223..090eb002 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index 35daa3df..f87d35db 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBDurationRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBDurationRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -88,7 +92,7 @@ typedef struct GPBDuration__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDuration__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h index 4d36174d..e0ed3e16 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 1bdd4949..9b60f36d 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBEmptyRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBEmptyRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -64,7 +68,7 @@ typedef struct GPBEmpty__storage_ { fields:NULL fieldCount:0 storageSize:sizeof(GPBEmpty__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index 491463f9..14ed5379 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index 2721fdfa..4dc8409c 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBFieldMaskRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBFieldMaskRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -77,7 +81,7 @@ typedef struct GPBFieldMask__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFieldMask__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h index d9450057..417562c0 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index 6e3c9c07..648d736c 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBSourceContextRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBSourceContextRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -77,7 +81,7 @@ typedef struct GPBSourceContext__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBSourceContext__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index a5b31cd0..163b39ba 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index 8ea1f124..bc9f23ff 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -28,6 +28,9 @@ @implementation GPBStructRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBStructRoot_FileDescriptor @@ -39,6 +42,7 @@ static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -110,7 +114,7 @@ typedef struct GPBStruct__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStruct__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -152,7 +156,7 @@ typedef struct GPBValue__storage_ { .number = GPBValue_FieldNumber_NullValue, .hasIndex = -1, .offset = (uint32_t)offsetof(GPBValue__storage_, nullValue), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, { @@ -208,7 +212,7 @@ typedef struct GPBValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; static const char *oneofs[] = { "kind", }; @@ -274,7 +278,7 @@ typedef struct GPBListValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBListValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index ebfa670f..094e9b6b 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 06e3ef94..1506dff3 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBTimestampRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBTimestampRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -88,7 +92,7 @@ typedef struct GPBTimestamp__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBTimestamp__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 05411958..da923c30 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index 6c7b4efd..a36f1cd4 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -31,18 +31,8 @@ @implementation GPBTypeRoot -+ (GPBExtensionRegistry*)extensionRegistry { - // This is called by +initialize so there is no need to worry - // about thread safety and initialization of registry. - static GPBExtensionRegistry* registry = nil; - if (!registry) { - GPBDebugCheckRuntimeVersion(); - registry = [[GPBExtensionRegistry alloc] init]; - [registry addExtensions:[GPBAnyRoot extensionRegistry]]; - [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; - } - return registry; -} +// No extensions in the file and none of the imports (direct or indirect) +// defined extensions, so no need to generate +extensionRegistry. @end @@ -55,6 +45,7 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -172,7 +163,7 @@ typedef struct GPBType__storage_ { .number = GPBType_FieldNumber_Syntax, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBType__storage_, syntax), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, }; @@ -183,7 +174,7 @@ typedef struct GPBType__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBType__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -244,7 +235,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Kind, .hasIndex = 0, .offset = (uint32_t)offsetof(GPBField__storage_, kind), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, { @@ -253,7 +244,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_Cardinality, .hasIndex = 1, .offset = (uint32_t)offsetof(GPBField__storage_, cardinality), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, { @@ -280,7 +271,7 @@ typedef struct GPBField__storage_ { .number = GPBField_FieldNumber_TypeURL, .hasIndex = 4, .offset = (uint32_t)offsetof(GPBField__storage_, typeURL), - .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldTextFormatNameCustom), .dataType = GPBDataTypeString, }, { @@ -336,7 +327,7 @@ typedef struct GPBField__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBField__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; @@ -553,7 +544,7 @@ typedef struct GPBEnum__storage_ { .number = GPBEnum_FieldNumber_Syntax, .hasIndex = 2, .offset = (uint32_t)offsetof(GPBEnum__storage_, syntax), - .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor), .dataType = GPBDataTypeEnum, }, }; @@ -564,7 +555,7 @@ typedef struct GPBEnum__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnum__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -641,7 +632,7 @@ typedef struct GPBEnumValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBEnumValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -695,7 +686,7 @@ typedef struct GPBOption__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBOption__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h index e397c480..2bf6fd29 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -13,7 +13,7 @@ #import "GPBProtocolBuffers.h" #endif -#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30001 +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30002 #error This file was generated by a different version of protoc which is incompatible with your Protocol Buffer library sources. #endif diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index b5405a7d..c8fdeb08 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -27,6 +27,9 @@ @implementation GPBWrappersRoot +// No extensions in the file and no imports, so no need to generate +// +extensionRegistry. + @end #pragma mark - GPBWrappersRoot_FileDescriptor @@ -38,6 +41,7 @@ static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { if (!descriptor) { GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + objcPrefix:@"GPB" syntax:GPBFileSyntaxProto3]; } return descriptor; @@ -77,7 +81,7 @@ typedef struct GPBDoubleValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBDoubleValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -120,7 +124,7 @@ typedef struct GPBFloatValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBFloatValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -163,7 +167,7 @@ typedef struct GPBInt64Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt64Value__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -206,7 +210,7 @@ typedef struct GPBUInt64Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt64Value__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -249,7 +253,7 @@ typedef struct GPBInt32Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBInt32Value__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -292,7 +296,7 @@ typedef struct GPBUInt32Value__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBUInt32Value__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -334,7 +338,7 @@ typedef struct GPBBoolValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBoolValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -377,7 +381,7 @@ typedef struct GPBStringValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBStringValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } @@ -420,7 +424,7 @@ typedef struct GPBBytesValue__storage_ { fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) storageSize:sizeof(GPBBytesValue__storage_) - flags:0]; + flags:GPBDescriptorInitializationFlag_None]; NSAssert(descriptor == nil, @"Startup recursed!"); descriptor = localDescriptor; } diff --git a/protobuf.bzl b/protobuf.bzl index c5555fde..e356f53c 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -62,9 +62,19 @@ def _proto_gen_impl(ctx): if ctx.attr.gen_py: args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir] - if ctx.executable.grpc_cpp_plugin: - args += ["--plugin=protoc-gen-grpc=" + ctx.executable.grpc_cpp_plugin.path] - args += ["--grpc_out=" + ctx.var["GENDIR"] + "/" + gen_dir] + if ctx.executable.plugin: + plugin = ctx.executable.plugin + lang = ctx.attr.plugin_language + if not lang and plugin.basename.startswith('protoc-gen-'): + lang = plugin.basename[len('protoc-gen-'):] + if not lang: + fail("cannot infer the target language of plugin", "plugin_language") + + outdir = ctx.var["GENDIR"] + "/" + gen_dir + if ctx.attr.plugin_options: + outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir + args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)] + args += ["--%s_out=%s" % (lang, outdir)] if args: ctx.action( @@ -72,6 +82,7 @@ def _proto_gen_impl(ctx): outputs=ctx.outputs.outs, arguments=args + import_flags + [s.path for s in srcs], executable=ctx.executable.protoc, + mnemonic="ProtoCompile", ) return struct( @@ -82,22 +93,24 @@ def _proto_gen_impl(ctx): ), ) -_proto_gen = rule( +proto_gen = rule( attrs = { "srcs": attr.label_list(allow_files = True), "deps": attr.label_list(providers = ["proto"]), "includes": attr.string_list(), "protoc": attr.label( - cfg = HOST_CFG, + cfg = "host", executable = True, single_file = True, mandatory = True, ), - "grpc_cpp_plugin": attr.label( - cfg = HOST_CFG, + "plugin": attr.label( + cfg = "host", + allow_files = True, executable = True, - single_file = True, ), + "plugin_language": attr.string(), + "plugin_options": attr.string_list(), "gen_cc": attr.bool(), "gen_py": attr.bool(), "outs": attr.output_list(), @@ -105,6 +118,26 @@ _proto_gen = rule( output_to_genfiles = True, implementation = _proto_gen_impl, ) +"""Generates codes from Protocol Buffers definitions. + +This rule helps you to implement Skylark macros specific to the target +language. You should prefer more specific `cc_proto_library `, +`py_proto_library` and others unless you are adding such wrapper macros. + +Args: + srcs: Protocol Buffers definition files (.proto) to run the protocol compiler + against. + deps: a list of dependency labels; must be other proto libraries. + includes: a list of include paths to .proto files. + protoc: the label of the protocol compiler to generate the sources. + plugin: the label of the protocol compiler plugin to be passed to the protocol + compiler. + plugin_language: the language of the generated sources + plugin_options: a list of options to be passed to the plugin + gen_cc: generates C++ sources in addition to the ones from the plugin. + gen_py: generates Python sources in addition to the ones from the plugin. + outs: a list of labels of the expected outputs from the protocol compiler. +""" def cc_proto_library( name, @@ -150,7 +183,7 @@ def cc_proto_library( if internal_bootstrap_hack: # For pre-checked-in generated files, we add the internal_bootstrap_hack # which will skip the codegen action. - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], @@ -170,13 +203,14 @@ def cc_proto_library( outs = _CcOuts(srcs, use_grpc_plugin) - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], includes=includes, protoc=protoc, - grpc_cpp_plugin=grpc_cpp_plugin, + plugin=grpc_cpp_plugin, + plugin_language="grpc", gen_cc=1, outs=outs, visibility=["//visibility:public"], @@ -286,7 +320,7 @@ def py_proto_library( if include != None: includes = [include] - _proto_gen( + proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 20e5d245..6f3b818a 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -636,7 +636,7 @@ class ReflectionTest(unittest.TestCase): if struct.calcsize('L') == 4: # Python only has signed ints, so 32-bit python can't fit an uint32 # in an int. - TestGetAndDeserialize('optional_uint32', 1 << 31, long) + TestGetAndDeserialize('optional_uint32', 1 << 31, integer_64) else: # 64-bit python can fit uint32 inside an int TestGetAndDeserialize('optional_uint32', 1 << 31, int) diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index dd21a046..08c72bcc 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -255,10 +255,54 @@ typedef struct { // value into the map. typedef struct { VALUE map; + const map_handlerdata_t* handlerdata; char key_storage[NATIVE_SLOT_MAX_SIZE]; char value_storage[NATIVE_SLOT_MAX_SIZE]; } map_parse_frame_t; +static void MapParseFrame_mark(void* _self) { + map_parse_frame_t* frame = _self; + + // This shouldn't strictly be necessary since this should be rooted by the + // message itself, but it can't hurt. + rb_gc_mark(frame->map); + + native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage); + native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage); +} + +void MapParseFrame_free(void* self) { + xfree(self); +} + +rb_data_type_t MapParseFrame_type = { + "MapParseFrame", + { MapParseFrame_mark, MapParseFrame_free, NULL }, +}; + +// Array of Ruby objects wrapping map_parse_frame_t. +// We don't allow multiple concurrent decodes, so we assume that this global +// variable is specific to the "current" decode. +VALUE map_parse_frames; + +static map_parse_frame_t* map_push_frame(VALUE map, + const map_handlerdata_t* handlerdata) { + map_parse_frame_t* frame = ALLOC(map_parse_frame_t); + frame->handlerdata = handlerdata; + frame->map = map; + native_slot_init(handlerdata->key_field_type, &frame->key_storage); + native_slot_init(handlerdata->value_field_type, &frame->value_storage); + + rb_ary_push(map_parse_frames, + TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame)); + + return frame; +} + +static void map_pop_frame() { + rb_ary_pop(map_parse_frames); +} + // Handler to begin a map entry: allocates a temporary frame. This is the // 'startsubmsg' handler on the msgdef that contains the map field. static void *startmapentry_handler(void *closure, const void *hd) { @@ -266,13 +310,7 @@ static void *startmapentry_handler(void *closure, const void *hd) { const map_handlerdata_t* mapdata = hd; VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE); - map_parse_frame_t* frame = ALLOC(map_parse_frame_t); - frame->map = map_rb; - - native_slot_init(mapdata->key_field_type, &frame->key_storage); - native_slot_init(mapdata->value_field_type, &frame->value_storage); - - return frame; + return map_push_frame(map_rb, mapdata); } // Handler to end a map entry: inserts the value defined during the message into @@ -298,7 +336,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { &frame->value_storage); Map_index_set(frame->map, key, value); - xfree(frame); + map_pop_frame(); return true; } @@ -737,6 +775,10 @@ VALUE Message_decode(VALUE klass, VALUE data) { msg_rb = rb_class_new_instance(0, NULL, msgklass); TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); + // We generally expect this to be clear already, but clear it in case parsing + // previously got interrupted somehow. + rb_ary_clear(map_parse_frames); + { const upb_pbdecodermethod* method = msgdef_decodermethod(desc); const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); @@ -781,6 +823,10 @@ VALUE Message_decode_json(VALUE klass, VALUE data) { msg_rb = rb_class_new_instance(0, NULL, msgklass); TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); + // We generally expect this to be clear already, but clear it in case parsing + // previously got interrupted somehow. + rb_ary_clear(map_parse_frames); + { const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc); stackenv se; diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c index 7cde4aec..98963667 100644 --- a/ruby/ext/google/protobuf_c/protobuf.c +++ b/ruby/ext/google/protobuf_c/protobuf.c @@ -112,4 +112,6 @@ void Init_protobuf_c() { upb_def_to_ruby_obj_map = rb_hash_new(); rb_gc_register_address(&upb_def_to_ruby_obj_map); + map_parse_frames = rb_ary_new(); + rb_gc_register_address(&map_parse_frames); } diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 08b8d516..d5ced567 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -166,6 +166,8 @@ extern VALUE cBuilder; extern VALUE cError; extern VALUE cParseError; +extern VALUE map_parse_frames; + // We forward-declare all of the Ruby method implementations here because we // sometimes call the methods directly across .c files, rather than going // through Ruby's method dispatching (e.g. during message parse). It's cleaner diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c index 976a3934..544ebc04 100644 --- a/ruby/ext/google/protobuf_c/upb.c +++ b/ruby/ext/google/protobuf_c/upb.c @@ -11175,7 +11175,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { sel = getsel_for_handlertype(p, UPB_HANDLER_STRING); upb_sink_putstring(&subsink, sel, buf, len, NULL); sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - upb_sink_endstr(&subsink, sel); + upb_sink_endstr(&p->top->sink, sel); multipart_end(p); break; } diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index cfb30786..e8c2a178 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -1005,7 +1005,7 @@ void Method::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 0ebf9b6a..dee438c6 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -719,6 +719,11 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } +TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) { + EXPECT_EQ("The system cannot find the file specified.\r\n", + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); +} + #endif // defined(_WIN32) || defined(__CYGWIN__) TEST_F(CommandLineInterfaceTest, PathLookup) { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 405a5fed..69cd5f3c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -2419,7 +2419,7 @@ GenerateClear(io::Printer* printer) { " &reinterpret_cast<$classname$*>(16)->f)\n" "#endif\n\n" "#define ZR_(first, last) do {\\\n" - " ::memset(&first, 0,\\\n" + " ::memset(&(first), 0,\\\n" " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" "} while (0)\n\n"; for (int i = 0; i < runs_of_fields_.size(); i++) { @@ -2956,7 +2956,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // on the CodedOutputStream. printer->Print( " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n" - " ::google::protobuf::internal::NewPermanentCallback(\n" + " ::google::protobuf::NewPermanentCallback(\n" " &MutableUnknownFieldsFor$classname$, this));\n" " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" " &unknown_fields_string, false);\n", diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 5d82946d..b7b6039a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -1252,7 +1252,7 @@ class GeneratedServiceTest : public testing::Test { foo_(descriptor_->FindMethodByName("Foo")), bar_(descriptor_->FindMethodByName("Bar")), stub_(&mock_channel_), - done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {} + done_(NewPermanentCallback(&DoNothing)) {} virtual void SetUp() { ASSERT_TRUE(foo_ != NULL); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index c0e7253a..d0de1eca 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -85,7 +85,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( if (descriptor_->containing_type()->options().message_set_wire_format()) options.push_back("GPBExtensionSetWireFormat"); - vars["options"] = BuildFlagsString(options); + vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options); ObjectiveCType objc_type = GetObjectiveCType(descriptor_); string singular_type; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index d2a6e882..527b7c0c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -93,7 +93,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, field_flags.push_back("GPBFieldHasEnumDescriptor"); } - (*variables)["fieldflags"] = BuildFlagsString(field_flags); + (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); (*variables)["default"] = DefaultValue(descriptor); (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 1b7b2783..878a3743 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -37,6 +37,7 @@ #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/stubs/stl_util.h> #include <google/protobuf/stubs/strutil.h> +#include <algorithm> // std::find() #include <iostream> #include <sstream> @@ -45,21 +46,122 @@ namespace google { namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { // This is also found in GPBBootstrap.h, and needs to be kept in sync. It // is the version check done to ensure generated code works with the current // runtime being used. -const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; +const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30002; const char* kHeaderExtension = ".pbobjc.h"; -namespace compiler { -namespace objectivec { +// Checks if a message contains any extension definitions (on the message or +// a nested message under it). +bool MessageContainsExtensions(const Descriptor* message) { + if (message->extension_count() > 0) { + return true; + } + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsExtensions(message->nested_type(i))) { + return true; + } + } + return false; +} + +// Checks if the file contains any extensions definitions (at the root or +// nested under a message). +bool FileContainsExtensions(const FileDescriptor* file) { + if (file->extension_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsExtensions(file->message_type(i))) { + return true; + } + } + return false; +} + +// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all +// deps as visited and prunes them from the needed files list. +void PruneFileAndDepsMarkingAsVisited( + const FileDescriptor* file, + vector<const FileDescriptor*>* files, + set<const FileDescriptor*>* files_visited) { + vector<const FileDescriptor*>::iterator iter = + std::find(files->begin(), files->end(), file); + if (iter != files->end()) { + files->erase(iter); + } + files_visited->insert(file); + for (int i = 0; i < file->dependency_count(); i++) { + PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited); + } +} + +// Helper for CollectMinimalFileDepsContainingExtensions. +void CollectMinimalFileDepsContainingExtensionsWorker( + const FileDescriptor* file, + vector<const FileDescriptor*>* files, + set<const FileDescriptor*>* files_visited) { + if (files_visited->find(file) != files_visited->end()) { + return; + } + files_visited->insert(file); + + if (FileContainsExtensions(file)) { + files->push_back(file); + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + PruneFileAndDepsMarkingAsVisited(dep, files, files_visited); + } + } else { + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + files_visited); + } + } +} + +// Collect the deps of the given file that contain extensions. This can be used to +// create the chain of roots that need to be wired together. +// +// NOTE: If any changes are made to this and the supporting functions, you will +// need to manually validate what the generated code is for the test files: +// objectivec/Tests/unittest_extension_chain_*.proto +// There are comments about what the expected code should be line and limited +// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports +// specifically). +void CollectMinimalFileDepsContainingExtensions( + const FileDescriptor* file, + vector<const FileDescriptor*>* files) { + set<const FileDescriptor*> files_visited; + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + &files_visited); + } +} + +bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { + for (int i = 0; i < file->dependency_count(); i++) { + if (dep == file->dependency(i)) { + return true; + } + } + return false; +} + +} // namespace FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) : file_(file), root_class_name_(FileClassName(file)), - is_public_dep_(false), options_(options) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); @@ -78,8 +180,6 @@ FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) } FileGenerator::~FileGenerator() { - STLDeleteContainerPointers(dependency_generators_.begin(), - dependency_generators_.end()); STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); STLDeleteContainerPointers(message_generators_.begin(), message_generators_.end()); @@ -105,14 +205,9 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { ImportWriter import_writer( options_.generate_for_named_framework, options_.named_framework_to_proto_path_mappings_path); - const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); const string header_extension(kHeaderExtension); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if ((*iter)->IsPublicDependency()) { - import_writer.AddFile((*iter)->file_, header_extension); - } + for (int i = 0; i < file_->public_dependency_count(); i++) { + import_writer.AddFile(file_->public_dependency(i), header_extension); } import_writer.Print(printer); } @@ -212,6 +307,9 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // #import the runtime support. PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h"); + vector<const FileDescriptor*> deps_with_extensions; + CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); + { ImportWriter import_writer( options_.generate_for_named_framework, @@ -223,13 +321,27 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // #import the headers for anything that a plain dependency of this proto // file (that means they were just an include, not a "public" include). - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if (!(*iter)->IsPublicDependency()) { - import_writer.AddFile((*iter)->file_, header_extension); + set<string> public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } + for (int i = 0; i < file_->dependency_count(); i++) { + const FileDescriptor *dep = file_->dependency(i); + bool public_import = (public_import_names.count(dep->name()) != 0); + if (!public_import) { + import_writer.AddFile(dep, header_extension); + } + } + + // If any indirect dependency provided extensions, it needs to be directly + // imported so it can get merged into the root's extensions registry. + // See the Note by CollectMinimalFileDepsContainingExtensions before + // changing this. + for (vector<const FileDescriptor *>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + if (!IsDirectDependency(*iter, file_)) { + import_writer.AddFile(*iter, header_extension); } } @@ -269,29 +381,11 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "@implementation $root_class_name$\n\n", "root_class_name", root_class_name_); - // Generate the extension initialization structures for the top level and - // any nested messages. - ostringstream extensions_stringstream; - if (file_->extension_count() + file_->message_type_count() > 0) { - io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); - io::Printer extensions_printer(&extensions_outputstream, '$'); - for (vector<ExtensionGenerator *>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); - } - for (vector<MessageGenerator *>::iterator iter = - message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); - } - extensions_stringstream.flush(); - } + const bool file_contains_extensions = FileContainsExtensions(file_); // If there were any extensions or this file has any dependencies, output // a registry to override to create the file specific registry. - const string& extensions_str = extensions_stringstream.str(); - if (extensions_str.length() > 0 || file_->dependency_count() > 0) { + if (file_contains_extensions || !deps_with_extensions.empty()) { printer->Print( "+ (GPBExtensionRegistry*)extensionRegistry {\n" " // This is called by +initialize so there is no need to worry\n" @@ -304,11 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Indent(); printer->Indent(); - if (extensions_str.length() > 0) { + if (file_contains_extensions) { printer->Print( "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - printer->Print(extensions_str.c_str()); + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); + } + for (vector<MessageGenerator *>::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); + } printer->Outdent(); printer->Print( "};\n" @@ -321,14 +424,21 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "}\n"); } - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { + if (deps_with_extensions.empty()) { printer->Print( - "[registry addExtensions:[$dependency$ extensionRegistry]];\n", - "dependency", (*iter)->RootClassName()); + "// None of the imports (direct or indirect) defined extensions, so no need to add\n" + "// them to this registry.\n"); + } else { + printer->Print( + "// Merge in the imports (direct or indirect) that defined extensions.\n"); + for (vector<const FileDescriptor *>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + const string root_class_name(FileClassName((*iter))); + printer->Print( + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", root_class_name); + } } printer->Outdent(); @@ -337,27 +447,39 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Print( " }\n" " return registry;\n" - "}\n" - "\n"); + "}\n"); + } else { + if (file_->dependency_count() > 0) { + printer->Print( + "// No extensions in the file and none of the imports (direct or indirect)\n" + "// defined extensions, so no need to generate +extensionRegistry.\n"); + } else { + printer->Print( + "// No extensions in the file and no imports, so no need to generate\n" + "// +extensionRegistry.\n"); + } } - printer->Print("@end\n\n"); + printer->Print("\n@end\n\n"); // File descriptor only needed if there are messages to use it. if (message_generators_.size() > 0) { - string syntax; + map<string, string> vars; + vars["root_class_name"] = root_class_name_; + vars["package"] = file_->package(); + vars["objc_prefix"] = FileClassPrefix(file_); switch (file_->syntax()) { case FileDescriptor::SYNTAX_UNKNOWN: - syntax = "GPBFileSyntaxUnknown"; + vars["syntax"] = "GPBFileSyntaxUnknown"; break; case FileDescriptor::SYNTAX_PROTO2: - syntax = "GPBFileSyntaxProto2"; + vars["syntax"] = "GPBFileSyntaxProto2"; break; case FileDescriptor::SYNTAX_PROTO3: - syntax = "GPBFileSyntaxProto3"; + vars["syntax"] = "GPBFileSyntaxProto3"; break; } - printer->Print( + printer->Print(vars, "#pragma mark - $root_class_name$_FileDescriptor\n" "\n" "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" @@ -365,16 +487,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) { " // about thread safety of the singleton.\n" " static GPBFileDescriptor *descriptor = NULL;\n" " if (!descriptor) {\n" - " GPBDebugCheckRuntimeVersion();\n" - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " syntax:$syntax$];\n" + " GPBDebugCheckRuntimeVersion();\n"); + if (vars["objc_prefix"].size() > 0) { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " objcPrefix:@\"$objc_prefix$\"\n" + " syntax:$syntax$];\n"); + } else { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n"); + } + printer->Print( " }\n" " return descriptor;\n" "}\n" - "\n", - "root_class_name", root_class_name_, - "package", file_->package(), - "syntax", syntax); + "\n"); } for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); @@ -393,24 +523,6 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "// @@protoc_insertion_point(global_scope)\n"); } -const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { - if (file_->dependency_count() != dependency_generators_.size()) { - set<string> public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } - for (int i = 0; i < file_->dependency_count(); i++) { - FileGenerator *generator = - new FileGenerator(file_->dependency(i), options_); - const string& name = file_->dependency(i)->name(); - bool public_import = (public_import_names.count(name) != 0); - generator->SetIsPublicDependency(public_import); - dependency_generators_.push_back(generator); - } - } - return dependency_generators_; -} - // Helper to print the import of the runtime support at the top of generated // files. This currently only supports the runtime coming from a framework // as defined by the official CocoaPod. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 60b19f19..a60a6885 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -63,29 +63,16 @@ class FileGenerator { const string& RootClassName() const { return root_class_name_; } - bool IsPublicDependency() const { return is_public_dep_; } - - protected: - void SetIsPublicDependency(bool is_public_dep) { - is_public_dep_ = is_public_dep; - } - private: const FileDescriptor* file_; string root_class_name_; - // Access this field through the DependencyGenerators accessor call below. - // Do not reference it directly. - vector<FileGenerator*> dependency_generators_; - vector<EnumGenerator*> enum_generators_; vector<MessageGenerator*> message_generators_; vector<ExtensionGenerator*> extension_generators_; - bool is_public_dep_; const Options options_; - const vector<FileGenerator*>& DependencyGenerators(); void PrintFileRuntimePreamble( io::Printer* printer, const string& header_to_import) const; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index a0b6d6cb..36407467 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -45,10 +45,22 @@ ObjectiveCGenerator::ObjectiveCGenerator() {} ObjectiveCGenerator::~ObjectiveCGenerator() {} +bool ObjectiveCGenerator::HasGenerateAll() const { + return true; +} + bool ObjectiveCGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { + *error = "Unimplemented Generate() method. Call GenerateAll() instead."; + return false; +} + +bool ObjectiveCGenerator::GenerateAll(const vector<const FileDescriptor*>& files, + const string& parameter, + GeneratorContext* context, + string* error) const { // ----------------------------------------------------------------- // Parse generator options. These options are passed to the compiler using the // --objc_opt flag. The options are passed as a comma separated list of @@ -117,29 +129,32 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, // ----------------------------------------------------------------- - // Validate the objc prefix/package pairing. - if (!ValidateObjCClassPrefix(file, generation_options, error)) { + // Validate the objc prefix/package pairings. + if (!ValidateObjCClassPrefixes(files, generation_options, error)) { // *error will have been filled in. return false; } - FileGenerator file_generator(file, generation_options); - string filepath = FilePath(file); + for (int i = 0; i < files.size(); i++) { + const FileDescriptor* file = files[i]; + FileGenerator file_generator(file, generation_options); + string filepath = FilePath(file); - // Generate header. - { - scoped_ptr<io::ZeroCopyOutputStream> output( - output_directory->Open(filepath + ".pbobjc.h")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateHeader(&printer); - } + // Generate header. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateHeader(&printer); + } - // Generate m file. - { - scoped_ptr<io::ZeroCopyOutputStream> output( - output_directory->Open(filepath + ".pbobjc.m")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSource(&printer); + // Generate m file. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.m")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateSource(&printer); + } } return true; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index 09266b04..9d801d51 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -47,8 +47,15 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { ~ObjectiveCGenerator(); // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, string* error) const; + bool HasGenerateAll() const; + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const; + bool GenerateAll(const vector<const FileDescriptor*>& files, + const string& parameter, + GeneratorContext* context, + string* error) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 009d57f9..c7fd96ac 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -210,10 +210,14 @@ const char* const kReservedWordList[] = { hash_set<string> kReservedWords = MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); -string SanitizeNameForObjC(const string& input, const string& extension) { +string SanitizeNameForObjC(const string& input, + const string& extension, + string* out_suffix_added) { if (kReservedWords.count(input) > 0) { + if (out_suffix_added) *out_suffix_added = extension; return input + extension; } + if (out_suffix_added) out_suffix_added->clear(); return input; } @@ -262,6 +266,34 @@ bool IsSpecialName(const string& name, const string* special_names, return false; } +string GetZeroEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlag_None"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionNone"; + case FLAGTYPE_FIELD: + return "GPBFieldNone"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return "0"; + } +} + +string GetEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlags"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionOptions"; + case FLAGTYPE_FIELD: + return "GPBFieldFlags"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return string(); + } +} + } // namespace // Escape C++ trigraphs by escaping question marks to \? @@ -308,6 +340,12 @@ string BaseFileName(const FileDescriptor* file) { return basename; } +string FileClassPrefix(const FileDescriptor* file) { + // Default is empty string, no need to check has_objc_class_prefix. + string result = file->options().objc_class_prefix(); + return result; +} + string FilePath(const FileDescriptor* file) { string output; string basename; @@ -338,19 +376,13 @@ string FilePathBasename(const FileDescriptor* file) { return output; } -string FileClassPrefix(const FileDescriptor* file) { - // Default is empty string, no need to check has_objc_class_prefix. - string result = file->options().objc_class_prefix(); - return result; -} - string FileClassName(const FileDescriptor* file) { string name = FileClassPrefix(file); name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); name += "Root"; // There aren't really any reserved words that end in "Root", but playing // it safe and checking. - return SanitizeNameForObjC(name, "_RootClass"); + return SanitizeNameForObjC(name, "_RootClass", NULL); } string ClassNameWorker(const Descriptor* descriptor) { @@ -372,11 +404,15 @@ string ClassNameWorker(const EnumDescriptor* descriptor) { } string ClassName(const Descriptor* descriptor) { + return ClassName(descriptor, NULL); +} + +string ClassName(const Descriptor* descriptor, string* out_suffix_added) { // 1. Message names are used as is (style calls for CamelCase, trust it). // 2. Check for reserved word at the very end and then suffix things. string prefix = FileClassPrefix(descriptor->file()); string name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix + name, "_Class"); + return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added); } string EnumName(const EnumDescriptor* descriptor) { @@ -390,7 +426,7 @@ string EnumName(const EnumDescriptor* descriptor) { // yields Fixed_Class, Fixed_Size. string name = FileClassPrefix(descriptor->file()); name += ClassNameWorker(descriptor); - return SanitizeNameForObjC(name, "_Enum"); + return SanitizeNameForObjC(name, "_Enum", NULL); } string EnumValueName(const EnumValueDescriptor* descriptor) { @@ -405,7 +441,7 @@ string EnumValueName(const EnumValueDescriptor* descriptor) { const string& name = class_name + "_" + value_str; // There aren't really any reserved words with an underscore and a leading // capital letter, but playing it safe and checking. - return SanitizeNameForObjC(name, "_Value"); + return SanitizeNameForObjC(name, "_Value", NULL); } string EnumValueShortName(const EnumValueDescriptor* descriptor) { @@ -442,7 +478,7 @@ string UnCamelCaseEnumShortName(const string& name) { string ExtensionMethodName(const FieldDescriptor* descriptor) { const string& name = NameFromFieldDescriptor(descriptor); const string& result = UnderscoresToCamelCase(name, false); - return SanitizeNameForObjC(result, "_Extension"); + return SanitizeNameForObjC(result, "_Extension", NULL); } string FieldName(const FieldDescriptor* field) { @@ -457,7 +493,7 @@ string FieldName(const FieldDescriptor* field) { result += "_p"; } } - return SanitizeNameForObjC(result, "_p"); + return SanitizeNameForObjC(result, "_p", NULL); } string FieldNameCapitalized(const FieldDescriptor* field) { @@ -817,17 +853,21 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { return false; } -string BuildFlagsString(const vector<string>& strings) { +string BuildFlagsString(const FlagType flag_type, + const vector<string>& strings) { if (strings.size() == 0) { - return "0"; + return GetZeroEnumNameForFlagType(flag_type); + } else if (strings.size() == 1) { + return strings[0]; } - string string; + string string("(" + GetEnumNameForFlagType(flag_type) + ")("); for (size_t i = 0; i != strings.size(); ++i) { if (i > 0) { string.append(" | "); } string.append(strings[i]); } + string.append(")"); return string; } @@ -980,28 +1020,20 @@ bool LoadExpectedPackagePrefixes(const Options &generation_options, generation_options.expected_prefixes_path, &collector, out_error); } -} // namespace - -bool ValidateObjCClassPrefix(const FileDescriptor* file, - const Options& generation_options, - string* out_error) { +bool ValidateObjCClassPrefix( + const FileDescriptor* file, + const string& expected_prefixes_path, + const map<string, string>& expected_package_prefixes, + string* out_error) { const string prefix = file->options().objc_class_prefix(); const string package = file->package(); // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for warnings. - // Load any expected package prefixes to validate against those. - map<string, string> expected_package_prefixes; - if (!LoadExpectedPackagePrefixes(generation_options, - &expected_package_prefixes, - out_error)) { - return false; - } - // Check: Error - See if there was an expected prefix for the package and // report if it doesn't match (wrong or missing). - map<string, string>::iterator package_match = + map<string, string>::const_iterator package_match = expected_package_prefixes.find(package); if (package_match != expected_package_prefixes.end()) { // There was an entry, and... @@ -1050,7 +1082,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, // Look for any other package that uses the same prefix. string other_package_for_prefix; - for (map<string, string>::iterator i = expected_package_prefixes.begin(); + for (map<string, string>::const_iterator i = expected_package_prefixes.begin(); i != expected_package_prefixes.end(); ++i) { if (i->second == prefix) { other_package_for_prefix = i->first; @@ -1068,7 +1100,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, << "protoc:0: warning: File '" << file->name() << "' has no " << "package. Consider adding a new package to the proto and adding '" << "new.package = " << prefix << "' to the expected prefixes file (" - << generation_options.expected_prefixes_path << ")." << endl; + << expected_prefixes_path << ")." << endl; cerr.flush(); } else { // ... another package has declared the same prefix. @@ -1078,7 +1110,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, << prefix << "' as its prefix. Consider either adding a new package " << "to the proto, or reusing one of the packages already using this " << "prefix in the expected prefixes file (" - << generation_options.expected_prefixes_path << ")." << endl; + << expected_prefixes_path << ")." << endl; cerr.flush(); } return true; @@ -1094,7 +1126,7 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, "'; that prefix is already used for 'package " + other_package_for_prefix + ";'. It can only be reused by listing " + "it in the expected file (" + - generation_options.expected_prefixes_path + ")."; + expected_prefixes_path + ")."; return false; // Only report first usage of the prefix. } @@ -1105,13 +1137,39 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " consider adding it to the expected prefixes file (" - << generation_options.expected_prefixes_path << ")." << endl; + << expected_prefixes_path << ")." << endl; cerr.flush(); } return true; } +} // namespace + +bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files, + const Options& generation_options, + string* out_error) { + // Load the expected package prefixes, if available, to validate against. + map<string, string> expected_package_prefixes; + if (!LoadExpectedPackagePrefixes(generation_options, + &expected_package_prefixes, + out_error)) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + bool is_valid = + ValidateObjCClassPrefix(files[i], + generation_options.expected_prefixes_path, + expected_package_prefixes, + out_error); + if (!is_valid) { + return false; + } + } + return true; +} + TextFormatDecodeData::TextFormatDecodeData() { } TextFormatDecodeData::~TextFormatDecodeData() { } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 344723a6..d17d44aa 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -67,6 +67,9 @@ bool IsRetainedName(const string& name); // handling under ARC. bool IsInitName(const string& name); +// Gets the objc_class_prefix. +string FileClassPrefix(const FileDescriptor* file); + // Gets the path of the file we're going to generate (sans the .pb.h // extension). The path will be dependent on the objectivec package // declared in the proto package. @@ -83,6 +86,7 @@ string FileClassName(const FileDescriptor* file); // These return the fully-qualified class name corresponding to the given // descriptor. string ClassName(const Descriptor* descriptor); +string ClassName(const Descriptor* descriptor, string* out_suffix_added); string EnumName(const EnumDescriptor* descriptor); // Returns the fully-qualified name of the enum value corresponding to the @@ -137,6 +141,12 @@ enum ObjectiveCType { OBJECTIVECTYPE_MESSAGE }; +enum FlagType { + FLAGTYPE_DESCRIPTOR_INITIALIZATION, + FLAGTYPE_EXTENSION, + FLAGTYPE_FIELD +}; + template<class TDescriptor> string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) { if (descriptor->options().deprecated()) { @@ -168,7 +178,7 @@ string GPBGenericValueFieldName(const FieldDescriptor* field); string DefaultValue(const FieldDescriptor* field); bool HasNonZeroDefaultValue(const FieldDescriptor* field); -string BuildFlagsString(const vector<string>& strings); +string BuildFlagsString(const FlagType type, const vector<string>& strings); // Builds HeaderDoc/appledoc style comments out of the comments in the .proto // file. @@ -185,12 +195,12 @@ string ProtobufFrameworkImportSymbol(const string& framework_name); // Checks if the file is one of the proto's bundled with the library. bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); -// Checks the prefix for a given file and outputs any warnings needed, if -// there are flat out errors, then out_error is filled in and the result is -// false. -bool ValidateObjCClassPrefix(const FileDescriptor* file, - const Options& generation_options, - string* out_error); +// Checks the prefix for the given files and outputs any warnings as needed. If +// there are flat out errors, then out_error is filled in with the first error +// and the result is false. +bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files, + const Options& generation_options, + string* out_error); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the expected output. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index ac5d8aea..0bc9dc10 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -115,7 +115,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } - variables_["fieldflags"] = BuildFlagsString(field_flags); + variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); const bool value_is_object_type = diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 822da893..4c6e1b55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -521,7 +521,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { if (descriptor_->options().message_set_wire_format()) { init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); } - vars["init_flags"] = BuildFlagsString(init_flags); + vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, + init_flags); printer->Print( vars, @@ -579,6 +580,19 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " [localDescriptor setupExtensionRanges:ranges\n" " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); } + if (descriptor_->containing_type() != NULL) { + string parent_class_name = ClassName(descriptor_->containing_type()); + printer->Print( + " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n", + "parent_name", parent_class_name); + } + string suffix_added; + ClassName(descriptor_, &suffix_added); + if (suffix_added.size() > 0) { + printer->Print( + " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", + "suffix", suffix_added); + } printer->Print( " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" " descriptor = localDescriptor;\n" diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 214d7c9c..519ed8fc 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -525,7 +525,6 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SourceCodeInfo source_code_info; source_code_info_ = &source_code_info; - vector<string> top_doc_comments; if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. input_->NextWithComments(NULL, &upcoming_detached_comments_, diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 6e258664..e929e4fb 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -261,12 +261,12 @@ string Subprocess::Win32ErrorMessage(DWORD error_code) { char* message; // WTF? - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, 0, - (LPTSTR)&message, // NOT A BUG! - 0, NULL); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, 0, + (LPSTR)&message, // NOT A BUG! + 0, NULL); string result = message; LocalFree(message); diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 0028c708..92c70c0d 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -2533,7 +2533,7 @@ void DescriptorProto_ExtensionRange::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -2836,7 +2836,7 @@ void DescriptorProto_ReservedRange::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -7347,7 +7347,7 @@ void MethodDescriptorProto::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -8163,7 +8163,7 @@ void FileOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -9570,7 +9570,7 @@ void MessageOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -10183,7 +10183,7 @@ void FieldOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -11177,7 +11177,7 @@ void EnumOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -13033,7 +13033,7 @@ void UninterpretedOption::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -14918,7 +14918,7 @@ void GeneratedCodeInfo_Annotation::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 94ece18e..ed5cca4b 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -185,7 +185,7 @@ void Duration::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h index 87271c5e..bbd507a8 100644 --- a/src/google/protobuf/stubs/callback.h +++ b/src/google/protobuf/stubs/callback.h @@ -381,6 +381,8 @@ class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> { typename remove_reference<P5>::type p5_; }; +} // namespace internal + // See Closure. inline Closure* NewCallback(void (*function)()) { return new internal::FunctionClosure0(function, true); @@ -533,8 +535,6 @@ inline ResultCallback2<R, A1, A2>* NewPermanentCallback( p2, p3, p4, p5); } -} // namespace internal - // A function which does nothing. Useful for creating no-op callbacks, e.g.: // Closure* nothing = NewCallback(&DoNothing); void LIBPROTOBUF_EXPORT DoNothing(); diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 25bae9b0..f9e2cfd4 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -41,8 +41,6 @@ namespace google { namespace protobuf { -using internal::NewCallback; -using internal::NewPermanentCallback; namespace { // TODO(kenton): More tests. diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc index 37def58d..d5f7779e 100644 --- a/src/google/protobuf/stubs/once_unittest.cc +++ b/src/google/protobuf/stubs/once_unittest.cc @@ -43,7 +43,6 @@ namespace google { namespace protobuf { -using internal::NewCallback; namespace { class OnceInitTest : public testing::Test { @@ -128,11 +127,11 @@ class OnceInitTest : public testing::Test { }; TestThread* RunInitOnceInNewThread() { - return new TestThread(internal::NewCallback(this, &OnceInitTest::InitOnce)); + return new TestThread(NewCallback(this, &OnceInitTest::InitOnce)); } TestThread* RunInitRecursiveOnceInNewThread() { return new TestThread( - internal::NewCallback(this, &OnceInitTest::InitRecursiveOnce)); + NewCallback(this, &OnceInitTest::InitRecursiveOnce)); } enum State { diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index bc76c844..470512ed 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -141,12 +141,12 @@ void File::DeleteRecursively(const string& name, #ifdef _MSC_VER // This interface is so weird. - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data); + WIN32_FIND_DATAA find_data; + HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data); if (find_handle == INVALID_HANDLE_VALUE) { // Just delete it, whatever it is. - DeleteFile(name.c_str()); - RemoveDirectory(name.c_str()); + DeleteFileA(name.c_str()); + RemoveDirectoryA(name.c_str()); return; } @@ -156,15 +156,15 @@ void File::DeleteRecursively(const string& name, string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); - RemoveDirectory(path.c_str()); + RemoveDirectoryA(path.c_str()); } else { - DeleteFile(path.c_str()); + DeleteFileA(path.c_str()); } } - } while(FindNextFile(find_handle, &find_data)); + } while(FindNextFileA(find_handle, &find_data)); FindClose(find_handle); - RemoveDirectory(name.c_str()); + RemoveDirectoryA(name.c_str()); #else // Use opendir()! Yay! // lstat = Don't follow symbolic links. diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 542e5ed7..487e62b0 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -199,7 +199,7 @@ void Timestamp::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 7ba909ef..a2a7f282 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -1125,7 +1125,7 @@ void Field::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 1e8dab70..fa31f763 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -165,7 +165,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( if (current_ == NULL) { ow_->RenderBytes(name, value); } else { - RenderDataPiece(name, DataPiece(value, false, true)); + // Since StringPiece is essentially a pointer, takes a copy of "value" to + // avoid ownership issues. + string_values_.push_back(new string(value.ToString())); + RenderDataPiece(name, DataPiece(*string_values_.back(), false, true)); } return this; } diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 1825f556..73e05cfe 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -907,7 +907,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, // conversions as much as possible. Because ToSnakeCase sometimes returns the // wrong value. google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback( - ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow)); + NewPermanentCallback(&RenderOneFieldPath, ow)); return DecodeCompactFieldMaskPaths(data.str(), callback.get()); } diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index dacac5e0..24ff5fd6 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -128,6 +128,34 @@ TEST_F(JsonUtilTest, TestDefaultValues) { "\"repeatedMessageValue\":[]" "}", ToJson(m, options)); + + options.always_print_primitive_fields = true; + m.set_string_value("i am a test string value"); + m.set_bytes_value("i am a test bytes value"); + EXPECT_EQ( + "{\"boolValue\":false," + "\"int32Value\":0," + "\"int64Value\":\"0\"," + "\"uint32Value\":0," + "\"uint64Value\":\"0\"," + "\"floatValue\":0," + "\"doubleValue\":0," + "\"stringValue\":\"i am a test string value\"," + "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\"," + "\"enumValue\":\"FOO\"," + "\"repeatedBoolValue\":[]," + "\"repeatedInt32Value\":[]," + "\"repeatedInt64Value\":[]," + "\"repeatedUint32Value\":[]," + "\"repeatedUint64Value\":[]," + "\"repeatedFloatValue\":[]," + "\"repeatedDoubleValue\":[]," + "\"repeatedStringValue\":[]," + "\"repeatedBytesValue\":[]," + "\"repeatedEnumValue\":[]," + "\"repeatedMessageValue\":[]" + "}", + ToJson(m, options)); } TEST_F(JsonUtilTest, ParseMessage) { diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index a6d0cb07..03a334b6 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -1389,8 +1389,7 @@ bool MessageDifferencer::MatchRepeatedFieldIndices( // doesn't necessarily imply Compare(b, c). Therefore a naive greedy // algorithm will fail to find a maximum matching. // Here we use the argumenting path algorithm. - MaximumMatcher::NodeMatchCallback* callback = - ::google::protobuf::internal::NewPermanentCallback( + MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback( this, &MessageDifferencer::IsMatch, repeated_field, key_comparator, &message1, &message2, parent_fields); |